mirror of
https://github.com/Laxilef/OTGateway.git
synced 2025-12-10 18:24:27 +05:00
* feat: added more hysteresis settings * fix: heating hysteresis switch fixed * refactor: added localization for hysteresis
1377 lines
58 KiB
HTML
1377 lines
58 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>settings.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="cn">CN</option>
|
|
<option value="it">IT</option>
|
|
<option value="nl">NL</option>
|
|
<option value="ru">RU</option>
|
|
</select>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
</header>
|
|
|
|
<main class="container">
|
|
<article>
|
|
<hgroup>
|
|
<h2 data-i18n>settings.name</h2>
|
|
<p></p>
|
|
</hgroup>
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.portal</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>
|
|
<span data-i18n>settings.portal.login</span>
|
|
<input type="text" name="portal[login]" maxlength="12">
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.portal.password</span>
|
|
<input type="password" name="portal[password]" maxlength="32">
|
|
</label>
|
|
</div>
|
|
|
|
<label>
|
|
<input type="checkbox" name="portal[auth]" value="true">
|
|
<span data-i18n>settings.portal.auth</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="portal[mdns]" value="true">
|
|
<span data-i18n>settings.portal.mdns</span>
|
|
</label>
|
|
<br />
|
|
|
|
<button type="submit" data-i18n>button.save</button>
|
|
</form>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.system</b></summary>
|
|
<div>
|
|
<div id="system-settings-busy" aria-busy="true"></div>
|
|
<form action="/api/settings" id="system-settings" class="hidden">
|
|
<fieldset>
|
|
<legend data-i18n>settings.system.unit</legend>
|
|
|
|
<label>
|
|
<input type="radio" name="system[unitSystem]" value="0" />
|
|
<span data-i18n>settings.system.metric</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="radio" name="system[unitSystem]" value="1" />
|
|
<span data-i18n>settings.system.imperial</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<fieldset>
|
|
<label>
|
|
<span data-i18n>settings.system.ntp.server</span>
|
|
<input type="text" name="system[ntp][server]" maxlength="48">
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.system.ntp.timezone</span>
|
|
<div role="group">
|
|
<input type="text" name="system[ntp][timezone]" maxlength="48">
|
|
<select class="presetTimezones">
|
|
<option disabled selected data-i18n>settings.system.ntp.timezonePresets</option>
|
|
</select>
|
|
</div>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<fieldset>
|
|
<label>
|
|
<span data-i18n>settings.system.statusLedGpio</span>
|
|
<input type="number" inputmode="numeric" name="system[statusLedGpio]" min="0" max="254" step="1">
|
|
<small data-i18n>settings.note.blankNotUse</small>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<fieldset>
|
|
<legend data-i18n>settings.section.diag</legend>
|
|
|
|
<label>
|
|
<input type="checkbox" name="system[serial][enabled]" value="true">
|
|
<span data-i18n>settings.system.serial.enable</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="system[telnet][enabled]" value="true">
|
|
<span data-i18n>settings.system.telnet.enable</span>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.system.logLevel</span>
|
|
<select name="system[logLevel]">
|
|
<option value="0">SILENT</option>
|
|
<option value="1">FATAL</option>
|
|
<option value="2">ERROR</option>
|
|
<option value="3">WARNING</option>
|
|
<option value="4">INFO</option>
|
|
<option value="5">NOTICE</option>
|
|
<option value="6">TRACE</option>
|
|
<option value="7">VERBOSE</option>
|
|
</select>
|
|
</label>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.system.serial.baud</span>
|
|
<select name="system[serial][baudrate]" required>
|
|
<option value="9600">9600</option>
|
|
<option value="19200">19200</option>
|
|
<option value="38400">38400</option>
|
|
<option value="57600">57600</option>
|
|
<option value="74880">74880</option>
|
|
<option value="115200">115200</option>
|
|
</select>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.system.telnet.port.title</span>
|
|
<input type="number" inputmode="numeric" name="system[telnet][port]" min="1" max="65535" step="1" required>
|
|
<small data-i18n>settings.system.telnet.port.note</small>
|
|
</label>
|
|
</div>
|
|
|
|
<mark data-i18n>settings.note.restart</mark>
|
|
</fieldset>
|
|
|
|
<button type="submit" data-i18n>button.save</button>
|
|
</form>
|
|
</div>
|
|
</details>
|
|
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.heating</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>
|
|
<span data-i18n>settings.temp.min</span>
|
|
<input type="number" inputmode="numeric" name="heating[minTemp]" min="0" max="0" step="1" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.temp.max</span>
|
|
<input type="number" inputmode="numeric" name="heating[maxTemp]" min="0" max="0" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.heating.turboFactor</span>
|
|
<input type="number" inputmode="decimal" name="heating[turboFactor]" min="1.5" max="10" step="0.1" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.maxModulation</span>
|
|
<input type="number" inputmode="numeric" name="heating[maxModulation]" min="1" max="100" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.heating.hyst.title</b></summary>
|
|
|
|
<div>
|
|
<fieldset>
|
|
<label>
|
|
<input type="checkbox" name="heating[hysteresis][enabled]" value="true">
|
|
<span data-i18n>settings.enable</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.heating.hyst.value</span>
|
|
<input type="number" inputmode="decimal" name="heating[hysteresis][value]" min="0" max="5" step="0.05" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.heating.hyst.action.title</span>
|
|
<select name="heating[hysteresis][action]">
|
|
<option value="0" data-i18n>settings.heating.hyst.action.disableHeating</option>
|
|
<option value="1" data-i18n>settings.heating.hyst.action.set0target</option>
|
|
</select>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<small data-i18n>settings.heating.hyst.desc</small>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.ohProtection.title</b></summary>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.ohProtection.highTemp.title</span>
|
|
<input type="number" inputmode="numeric" name="heating[overheatProtection][highTemp]" min="0" max="0" step="1" required>
|
|
<small data-i18n>settings.ohProtection.highTemp.note</small>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.ohProtection.lowTemp.title</span>
|
|
<input type="number" inputmode="numeric" name="heating[overheatProtection][lowTemp]" min="0" max="0" step="1" required>
|
|
<small data-i18n>settings.ohProtection.lowTemp.note</small>
|
|
</label>
|
|
</div>
|
|
|
|
<small data-i18n>settings.ohProtection.desc</small>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.freezeProtection.title</b></summary>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.freezeProtection.lowTemp</span>
|
|
<input type="number" inputmode="numeric" name="heating[freezeProtection][lowTemp]" min="0" max="0" step="1" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.freezeProtection.thresholdTime</span>
|
|
<input type="number" inputmode="numeric" name="heating[freezeProtection][thresholdTime]" min="30" max="1800" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<small data-i18n>settings.freezeProtection.desc</small>
|
|
</details>
|
|
|
|
<br />
|
|
|
|
<button type="submit" data-i18n>button.save</button>
|
|
</form>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.dhw</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>
|
|
<span data-i18n>settings.temp.min</span>
|
|
<input type="number" inputmode="numeric" name="dhw[minTemp]" min="0" max="0" step="1" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.temp.max</span>
|
|
<input type="number" inputmode="numeric" name="dhw[maxTemp]" min="0" max="0" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<label>
|
|
<span data-i18n>settings.maxModulation</span>
|
|
<input type="number" inputmode="numeric" name="dhw[maxModulation]" min="1" max="100" step="1" required>
|
|
</label>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.ohProtection.title</b></summary>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.ohProtection.highTemp.title</span>
|
|
<input type="number" inputmode="numeric" name="dhw[overheatProtection][highTemp]" min="0" max="0" step="1" required>
|
|
<small data-i18n>settings.ohProtection.highTemp.note</small>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.ohProtection.lowTemp.title</span>
|
|
<input type="number" inputmode="numeric" name="dhw[overheatProtection][lowTemp]" min="0" max="0" step="1" required>
|
|
<small data-i18n>settings.ohProtection.lowTemp.note</small>
|
|
</label>
|
|
</div>
|
|
|
|
<small data-i18n>settings.ohProtection.desc</small>
|
|
</details>
|
|
|
|
<br />
|
|
|
|
<button type="submit" data-i18n>button.save</button>
|
|
</form>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.emergency</b></summary>
|
|
<div>
|
|
<div id="emergency-settings-busy" aria-busy="true"></div>
|
|
<form action="/api/settings" id="emergency-settings" class="hidden">
|
|
<fieldset>
|
|
<small data-i18n>settings.emergency.desc</small>
|
|
</fieldset>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.emergency.target.title</span>
|
|
<input type="number" inputmode="numeric" name="emergency[target]" min="0" max="0" step="1" required>
|
|
<small data-i18n>settings.emergency.target.note</small>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.emergency.treshold</span>
|
|
<input type="number" inputmode="numeric" name="emergency[tresholdTime]" min="60" max="1800" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<button type="submit" data-i18n>button.save</button>
|
|
</form>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.equitherm</b></summary>
|
|
<div>
|
|
<div id="equitherm-settings-busy" aria-busy="true"></div>
|
|
<form action="/api/settings" id="equitherm-settings" class="hidden">
|
|
<fieldset>
|
|
<label>
|
|
<input type="checkbox" name="equitherm[enabled]" value="true">
|
|
<span data-i18n>settings.enable</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<div>
|
|
<div>
|
|
<canvas id="etChart"></canvas>
|
|
</div>
|
|
|
|
<label>
|
|
<div>
|
|
<span data-i18n>settings.equitherm.chart.targetTemp</span>: <b class="etChartTargetTempValue"></b>°
|
|
</div>
|
|
<input class="etChartTargetTemp" type="range" value="0" min="0" max="0" step="0.5">
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.equitherm.slope.title</span>
|
|
<input type="number" inputmode="decimal" name="equitherm[slope]" min="0.001" max="10" step="0.001" required>
|
|
<small data-i18n>settings.equitherm.slope.note</small>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.equitherm.exponent.title</span>
|
|
<input type="number" inputmode="decimal" name="equitherm[exponent]" min="0.1" max="2" step="0.001" required>
|
|
<small data-i18n>settings.equitherm.exponent.note</small>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.equitherm.shift.title</span>
|
|
<input type="number" inputmode="decimal" name="equitherm[shift]" min="-15" max="15" step="0.01" required>
|
|
<small data-i18n>settings.equitherm.shift.note</small>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.equitherm.targetDiffFactor.title</span>
|
|
<input type="number" inputmode="decimal" name="equitherm[targetDiffFactor]" min="0" max="10" step="0.01" required>
|
|
<small data-i18n>settings.equitherm.targetDiffFactor.note</small>
|
|
</label>
|
|
</div>
|
|
|
|
<button type="submit" data-i18n>button.save</button>
|
|
</form>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.pid</b></summary>
|
|
<div>
|
|
<div id="pid-settings-busy" aria-busy="true"></div>
|
|
<form action="/api/settings" id="pid-settings" class="hidden">
|
|
<fieldset>
|
|
<label>
|
|
<input type="checkbox" name="pid[enabled]" value="true">
|
|
<span data-i18n>settings.enable</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.pid.p</span>
|
|
<input type="number" inputmode="decimal" name="pid[p_factor]" min="0.1" max="1000" step="0.01" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.pid.i</span>
|
|
<input type="number" inputmode="decimal" name="pid[i_factor]" min="0" max="100" step="0.0001" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.pid.d</span>
|
|
<input type="number" inputmode="decimal" name="pid[d_factor]" min="0" max="100000" step="0.1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<label>
|
|
<span data-i18n>settings.pid.dt</span>
|
|
<input type="number" inputmode="numeric" name="pid[dt]" min="30" max="1800" step="1" required>
|
|
</label>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.pid.limits.title</b></summary>
|
|
|
|
<div>
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.temp.min</span>
|
|
<input type="number" inputmode="decimal" name="pid[minTemp]" min="0" max="0" step="1" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.temp.max</span>
|
|
<input type="number" inputmode="numeric" name="pid[maxTemp]" min="0" max="0" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<small data-i18n>settings.pid.limits.note</small>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.pid.deadband.title</b></summary>
|
|
|
|
<div>
|
|
<fieldset>
|
|
<label>
|
|
<input type="checkbox" name="pid[deadband][enabled]" value="true">
|
|
<span data-i18n>settings.enable</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.pid.deadband.p_multiplier</span>
|
|
<input type="number" inputmode="decimal" name="pid[deadband][p_multiplier]" min="0" max="5" step="0.001" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.pid.deadband.i_multiplier</span>
|
|
<input type="number" inputmode="decimal" name="pid[deadband][i_multiplier]" min="0" max="1" step="0.001" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.pid.deadband.d_multiplier</span>
|
|
<input type="number" inputmode="decimal" name="pid[deadband][d_multiplier]" min="0" max="1" step="0.001" required>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.pid.deadband.thresholdHigh</span>
|
|
<input type="number" inputmode="decimal" name="pid[deadband][thresholdHigh]" min="0" max="5" step="0.01" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.pid.deadband.thresholdLow</span>
|
|
<input type="number" inputmode="decimal" name="pid[deadband][thresholdLow]" min="0" max="5" step="0.01" required>
|
|
</label>
|
|
</div>
|
|
|
|
<small data-i18n>settings.pid.deadband.note</small>
|
|
</div>
|
|
</details>
|
|
|
|
<br />
|
|
|
|
<button type="submit" data-i18n>button.save</button>
|
|
</form>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.ot</b></summary>
|
|
<div>
|
|
<div id="ot-settings-busy" aria-busy="true"></div>
|
|
<form action="/api/settings" id="ot-settings" class="hidden">
|
|
<fieldset>
|
|
<legend data-i18n>settings.system.unit</legend>
|
|
|
|
<label>
|
|
<input type="radio" name="opentherm[unitSystem]" value="0" />
|
|
<span data-i18n>settings.system.metric</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="radio" name="opentherm[unitSystem]" value="1" />
|
|
<span data-i18n>settings.system.imperial</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.ot.inGpio</span>
|
|
<input type="number" inputmode="numeric" name="opentherm[inGpio]" min="0" max="254" step="1">
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.ot.outGpio</span>
|
|
<input type="number" inputmode="numeric" name="opentherm[outGpio]" min="0" max="254" step="1">
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.ot.ledGpio</span>
|
|
<input type="number" inputmode="numeric" name="opentherm[rxLedGpio]" min="0" max="254" step="1">
|
|
<small data-i18n>settings.note.blankNotUse</small>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.ot.memberId</span>
|
|
<input type="number" inputmode="numeric" name="opentherm[memberId]" min="0" max="255" step="1" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.ot.flags</span>
|
|
<input type="number" inputmode="numeric" name="opentherm[flags]" min="0" max="255" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.ot.minPower.title</span>
|
|
<input type="number" inputmode="decimal" name="opentherm[minPower]" min="0" max="1000" step="0.01">
|
|
<small data-i18n>settings.ot.minPower.note</small>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.ot.maxPower.title</span>
|
|
<input type="number" inputmode="decimal" name="opentherm[maxPower]" min="0" max="1000" step="0.01">
|
|
<small data-i18n>settings.ot.maxPower.note</small>
|
|
</label>
|
|
</div>
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.ot.options.title</b></summary>
|
|
|
|
<div>
|
|
<fieldset>
|
|
<small data-i18n>settings.ot.options.desc</small>
|
|
</fieldset>
|
|
|
|
<fieldset>
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][dhwSupport]" value="true">
|
|
<span data-i18n>settings.ot.options.dhwSupport</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][coolingSupport]" value="true">
|
|
<span data-i18n>settings.ot.options.coolingSupport</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][summerWinterMode]" value="true">
|
|
<span data-i18n>settings.ot.options.summerWinterMode</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][heatingStateToSummerWinterMode]" value="true">
|
|
<span data-i18n>settings.ot.options.heatingStateToSummerWinterMode</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][ch2AlwaysEnabled]" value="true">
|
|
<span data-i18n>settings.ot.options.ch2AlwaysEnabled</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][heatingToCh2]" value="true">
|
|
<span data-i18n>settings.ot.options.heatingToCh2</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][dhwToCh2]" value="true">
|
|
<span data-i18n>settings.ot.options.dhwToCh2</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][dhwBlocking]" value="true">
|
|
<span data-i18n>settings.ot.options.dhwBlocking</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][dhwStateAsDhwBlocking]" value="true">
|
|
<span data-i18n>settings.ot.options.dhwStateAsDhwBlocking</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][maxTempSyncWithTargetTemp]" value="true">
|
|
<span data-i18n>settings.ot.options.maxTempSyncWithTargetTemp</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][getMinMaxTemp]" value="true">
|
|
<span data-i18n>settings.ot.options.getMinMaxTemp</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][ignoreDiagState]" value="true">
|
|
<span data-i18n>settings.ot.options.ignoreDiagState</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][autoFaultReset]" value="true">
|
|
<span data-i18n>settings.ot.options.autoFaultReset</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][autoDiagReset]" value="true">
|
|
<span data-i18n>settings.ot.options.autoDiagReset</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][setDateAndTime]" value="true">
|
|
<span data-i18n>settings.ot.options.setDateAndTime</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][immergasFix]" value="true">
|
|
<span data-i18n>settings.ot.options.immergasFix</span>
|
|
</label>
|
|
|
|
<hr />
|
|
|
|
<label>
|
|
<input type="checkbox" name="opentherm[options][nativeHeatingControl]" value="true">
|
|
<span data-i18n>settings.ot.nativeHeating.title</span><br />
|
|
<small data-i18n>settings.ot.nativeHeating.note</small>
|
|
</label>
|
|
</fieldset>
|
|
</div>
|
|
</details>
|
|
|
|
<br />
|
|
<button type="submit" data-i18n>button.save</button>
|
|
</form>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.mqtt</b></summary>
|
|
<div>
|
|
<div id="mqtt-settings-busy" aria-busy="true"></div>
|
|
<form action="/api/settings" id="mqtt-settings" class="hidden">
|
|
<fieldset>
|
|
<label>
|
|
<input type="checkbox" name="mqtt[enabled]" value="true">
|
|
<span data-i18n>settings.enable</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="mqtt[homeAssistantDiscovery]" value="true">
|
|
<span data-i18n>settings.mqtt.homeAssistantDiscovery</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.mqtt.server</span>
|
|
<input type="text" name="mqtt[server]" maxlength="80" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.mqtt.port</span>
|
|
<input type="number" inputmode="numeric" name="mqtt[port]" min="1" max="65535" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.mqtt.user</span>
|
|
<input type="text" name="mqtt[user]" maxlength="32">
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.mqtt.password</span>
|
|
<input type="password" name="mqtt[password]" maxlength="32">
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.mqtt.prefix</span>
|
|
<input type="text" name="mqtt[prefix]" maxlength="32" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.mqtt.interval</span>
|
|
<input type="number" inputmode="numeric" name="mqtt[interval]" min="3" max="60" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<button type="submit" data-i18n>button.save</button>
|
|
</form>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.extPump</b></summary>
|
|
<div>
|
|
<div id="extpump-settings-busy" aria-busy="true"></div>
|
|
<form action="/api/settings" id="extpump-settings" class="hidden">
|
|
<fieldset>
|
|
<label>
|
|
<input type="checkbox" name="externalPump[use]" value="true">
|
|
<span data-i18n>settings.extPump.use</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="externalPump[invertState]" value="true">
|
|
<span data-i18n>settings.externalPump.invertState</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.extPump.gpio</span>
|
|
<input type="number" inputmode="numeric" name="externalPump[gpio]" min="0" max="254" step="1">
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.extPump.postCirculationTime</span>
|
|
<input type="number" inputmode="numeric" name="externalPump[postCirculationTime]" min="1" max="120" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.extPump.antiStuckInterval</span>
|
|
<input type="number" inputmode="numeric" name="externalPump[antiStuckInterval]" min="1" max="366" step="1" required>
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.extPump.antiStuckTime</span>
|
|
<input type="number" inputmode="numeric" name="externalPump[antiStuckTime]" min="1" max="20" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<button type="submit" data-i18n>button.save</button>
|
|
</form>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>settings.section.cascadeControl</b></summary>
|
|
<div>
|
|
<div id="cc-settings-busy" aria-busy="true"></div>
|
|
<form action="/api/settings" id="cc-settings" class="hidden">
|
|
<fieldset>
|
|
<label>
|
|
<input type="checkbox" name="cascadeControl[input][enabled]" value="true">
|
|
<span data-i18n>settings.cascadeControl.input.enable</span>
|
|
<br />
|
|
<small data-i18n>settings.cascadeControl.input.desc</small>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="cascadeControl[input][invertState]" value="true">
|
|
<span data-i18n>settings.cascadeControl.input.invertState</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.cascadeControl.input.gpio</span>
|
|
<input type="number" inputmode="numeric" name="cascadeControl[input][gpio]" min="0" max="254" step="1">
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.cascadeControl.input.thresholdTime</span>
|
|
<input type="number" inputmode="numeric" name="cascadeControl[input][thresholdTime]" min="5" max="600" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<hr />
|
|
|
|
<fieldset>
|
|
<label>
|
|
<input type="checkbox" name="cascadeControl[output][enabled]" value="true">
|
|
<span data-i18n>settings.cascadeControl.output.enable</span>
|
|
<br />
|
|
<small data-i18n>settings.cascadeControl.output.desc</small>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="cascadeControl[output][invertState]" value="true">
|
|
<span data-i18n>settings.cascadeControl.output.invertState</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<div class="grid">
|
|
<label>
|
|
<span data-i18n>settings.cascadeControl.output.gpio</span>
|
|
<input type="number" inputmode="numeric" name="cascadeControl[output][gpio]" min="0" max="254" step="1">
|
|
</label>
|
|
|
|
<label>
|
|
<span data-i18n>settings.cascadeControl.output.thresholdTime</span>
|
|
<input type="number" inputmode="numeric" name="cascadeControl[output][thresholdTime]" min="5" max="600" step="1" required>
|
|
</label>
|
|
</div>
|
|
|
|
<fieldset>
|
|
<legend data-i18n>settings.cascadeControl.output.events.desc</legend>
|
|
|
|
<label>
|
|
<input type="checkbox" name="cascadeControl[output][onFault]" value="true">
|
|
<span data-i18n>settings.cascadeControl.output.events.onFault</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="cascadeControl[output][onLossConnection]" value="true">
|
|
<span data-i18n>settings.cascadeControl.output.events.onLossConnection</span>
|
|
</label>
|
|
|
|
<label>
|
|
<input type="checkbox" name="cascadeControl[output][onEnabledHeating]" value="true">
|
|
<span data-i18n>settings.cascadeControl.output.events.onEnabledHeating</span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
<button type="submit" data-i18n>button.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" 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 src="/static/chart.js?{BUILD_TIME}"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
const lang = new Lang(document.getElementById('lang'));
|
|
lang.build();
|
|
|
|
let etChart = null;
|
|
let etChartConfig = {
|
|
slope: null,
|
|
exponent: null,
|
|
shift: null,
|
|
unitSystem: null,
|
|
targetTemp: null,
|
|
minTemp: null,
|
|
maxTemp: null,
|
|
decimated: false
|
|
};
|
|
|
|
const hasNeedDecimationChart = () => {
|
|
return window.innerWidth <= 800;
|
|
}
|
|
|
|
const makeEquithermChart = () => {
|
|
if (etChart == null) {
|
|
const ctx = document.getElementById('etChart').getContext('2d');
|
|
|
|
try {
|
|
etChart = new Chart(ctx, {
|
|
type: 'line',
|
|
data: {
|
|
datasets: [{
|
|
borderColor: (context) => {
|
|
const chart = context.chart;
|
|
const { ctx, chartArea } = chart;
|
|
|
|
if (!chartArea) {
|
|
return;
|
|
}
|
|
|
|
const gradient = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top);
|
|
gradient.addColorStop(0, 'rgba(1, 114, 173, 1)');
|
|
gradient.addColorStop(0.5, 'rgba(255, 99, 132, 1)');
|
|
|
|
return gradient;
|
|
},
|
|
borderWidth: 3,
|
|
fill: false,
|
|
tension: 0.1,
|
|
pointRadius: 2,
|
|
pointHoverRadius: 4,
|
|
indexAxis: "x",
|
|
data: []
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
resizeDelay: 500,
|
|
parsing: false,
|
|
interaction: {
|
|
mode: 'nearest',
|
|
intersect: false
|
|
},
|
|
plugins: {
|
|
tooltip: {
|
|
enabled: true,
|
|
position: 'nearest',
|
|
displayColors: false,
|
|
callbacks: {
|
|
title: (items) => {
|
|
return `${i18n("settings.equitherm.chart.outdoorTemp")}: ${items[0].label}`;
|
|
}
|
|
}
|
|
},
|
|
legend: {
|
|
display: false
|
|
}
|
|
},
|
|
scales: {
|
|
x: {
|
|
display: true,
|
|
type: "linear",
|
|
reverse: true,
|
|
title: {
|
|
display: true
|
|
},
|
|
ticks: {
|
|
stepSize: 1,
|
|
format: {
|
|
style: "unit",
|
|
unit: "degree",
|
|
unitDisplay: "narrow"
|
|
}
|
|
}
|
|
},
|
|
y: {
|
|
display: true,
|
|
title: {
|
|
display: true
|
|
},
|
|
ticks: {
|
|
format: {
|
|
style: "unit",
|
|
unit: "degree",
|
|
unitDisplay: "narrow"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
|
|
if (!etChart) {
|
|
return;
|
|
}
|
|
|
|
let data = [];
|
|
etChartConfig.decimated = hasNeedDecimationChart();
|
|
for (let value = 30; value >= -30; value -= etChartConfig.decimated ? 2 : 1) {
|
|
const outdoorTemp = etChartConfig.unitSystem == 0 ? value : c2f(value);
|
|
|
|
data.push({
|
|
x: parseFloat(outdoorTemp.toFixed(1)),
|
|
y: parseFloat(calculateEquithermTemp(outdoorTemp).toFixed(1))
|
|
});
|
|
}
|
|
|
|
etChart.data.datasets[0].data = data;
|
|
etChart.data.datasets[0].label = i18n("settings.equitherm.chart.setpointTemp");
|
|
etChart.options.scales.x.title.text = i18n("settings.equitherm.chart.outdoorTemp");
|
|
etChart.options.scales.y.title.text = i18n("settings.equitherm.chart.setpointTemp");
|
|
etChart.update();
|
|
}
|
|
|
|
const calculateEquithermTemp = (outdoorTemp) => {
|
|
const tempDelta = etChartConfig.targetTemp - outdoorTemp;
|
|
const maxPoint = etChartConfig.targetTemp - (
|
|
etChartConfig.maxTemp - etChartConfig.targetTemp
|
|
) / etChartConfig.slope;
|
|
|
|
const sf = (etChartConfig.maxTemp - etChartConfig.targetTemp) / Math.pow(
|
|
etChartConfig.targetTemp - maxPoint,
|
|
1 / etChartConfig.exponent
|
|
);
|
|
const result = etChartConfig.targetTemp + etChartConfig.shift + sf * (
|
|
tempDelta >= 0
|
|
? Math.pow(tempDelta, 1 / etChartConfig.exponent)
|
|
: -(Math.pow(-(tempDelta), 1 / etChartConfig.exponent))
|
|
);
|
|
|
|
return Math.max(Math.min(result, etChartConfig.maxTemp), etChartConfig.minTemp);
|
|
}
|
|
|
|
const fillData = (data) => {
|
|
// System
|
|
setSelectValue("[name='system[logLevel]']", data.system.logLevel);
|
|
setCheckboxValue("[name='system[serial][enabled]']", data.system.serial.enabled);
|
|
setSelectValue("[name='system[serial][baudrate]']", data.system.serial.baudrate);
|
|
setCheckboxValue("[name='system[telnet][enabled]']", data.system.telnet.enabled);
|
|
setInputValue("[name='system[telnet][port]']", data.system.telnet.port);
|
|
setInputValue("[name='system[ntp][server]']", data.system.ntp.server);
|
|
setInputValue("[name='system[ntp][timezone]']", data.system.ntp.timezone);
|
|
setRadioValue("[name='system[unitSystem]']", data.system.unitSystem);
|
|
setInputValue("[name='system[statusLedGpio]']", data.system.statusLedGpio < 255 ? data.system.statusLedGpio : '');
|
|
setBusy('#system-settings-busy', '#system-settings', false);
|
|
|
|
// Portal
|
|
setCheckboxValue("[name='portal[auth]']", data.portal.auth);
|
|
setInputValue("[name='portal[login]']", data.portal.login);
|
|
setInputValue("[name='portal[password]']", data.portal.password);
|
|
setCheckboxValue("[name='portal[mdns]']", data.portal.mdns);
|
|
setBusy('#portal-settings-busy', '#portal-settings', false);
|
|
|
|
// Opentherm
|
|
setRadioValue("[name='opentherm[unitSystem]']", data.opentherm.unitSystem);
|
|
setInputValue("[name='opentherm[inGpio]']", data.opentherm.inGpio < 255 ? data.opentherm.inGpio : '');
|
|
setInputValue("[name='opentherm[outGpio]']", data.opentherm.outGpio < 255 ? data.opentherm.outGpio : '');
|
|
setInputValue("[name='opentherm[rxLedGpio]']", data.opentherm.rxLedGpio < 255 ? data.opentherm.rxLedGpio : '');
|
|
setInputValue("[name='opentherm[memberId]']", data.opentherm.memberId);
|
|
setInputValue("[name='opentherm[flags]']", data.opentherm.flags);
|
|
setInputValue("[name='opentherm[minPower]']", data.opentherm.minPower);
|
|
setInputValue("[name='opentherm[maxPower]']", data.opentherm.maxPower);
|
|
setCheckboxValue("[name='opentherm[options][dhwSupport]']", data.opentherm.options.dhwSupport);
|
|
setCheckboxValue("[name='opentherm[options][coolingSupport]']", data.opentherm.options.coolingSupport);
|
|
setCheckboxValue("[name='opentherm[options][summerWinterMode]']", data.opentherm.options.summerWinterMode);
|
|
setCheckboxValue("[name='opentherm[options][heatingStateToSummerWinterMode]']", data.opentherm.options.heatingStateToSummerWinterMode);
|
|
setCheckboxValue("[name='opentherm[options][ch2AlwaysEnabled]']", data.opentherm.options.ch2AlwaysEnabled);
|
|
setCheckboxValue("[name='opentherm[options][heatingToCh2]']", data.opentherm.options.heatingToCh2);
|
|
setCheckboxValue("[name='opentherm[options][dhwToCh2]']", data.opentherm.options.dhwToCh2);
|
|
setCheckboxValue("[name='opentherm[options][dhwBlocking]']", data.opentherm.options.dhwBlocking);
|
|
setCheckboxValue("[name='opentherm[options][dhwStateAsDhwBlocking]']", data.opentherm.options.dhwStateAsDhwBlocking);
|
|
setCheckboxValue("[name='opentherm[options][maxTempSyncWithTargetTemp]']", data.opentherm.options.maxTempSyncWithTargetTemp);
|
|
setCheckboxValue("[name='opentherm[options][getMinMaxTemp]']", data.opentherm.options.getMinMaxTemp);
|
|
setCheckboxValue("[name='opentherm[options][ignoreDiagState]']", data.opentherm.options.ignoreDiagState);
|
|
setCheckboxValue("[name='opentherm[options][autoFaultReset]']", data.opentherm.options.autoFaultReset);
|
|
setCheckboxValue("[name='opentherm[options][autoDiagReset]']", data.opentherm.options.autoDiagReset);
|
|
setCheckboxValue("[name='opentherm[options][setDateAndTime]']", data.opentherm.options.setDateAndTime);
|
|
setCheckboxValue("[name='opentherm[options][nativeHeatingControl]']", data.opentherm.options.nativeHeatingControl);
|
|
setCheckboxValue("[name='opentherm[options][immergasFix]']", data.opentherm.options.immergasFix);
|
|
setBusy('#ot-settings-busy', '#ot-settings', false);
|
|
|
|
// MQTT
|
|
setCheckboxValue("[name='mqtt[enabled]']", data.mqtt.enabled);
|
|
setCheckboxValue("[name='mqtt[homeAssistantDiscovery]']", data.mqtt.homeAssistantDiscovery);
|
|
setInputValue("[name='mqtt[server]']", data.mqtt.server);
|
|
setInputValue("[name='mqtt[port]']", data.mqtt.port);
|
|
setInputValue("[name='mqtt[user]']", data.mqtt.user);
|
|
setInputValue("[name='mqtt[password]']", data.mqtt.password);
|
|
setInputValue("[name='mqtt[prefix]']", data.mqtt.prefix);
|
|
setInputValue("[name='mqtt[interval]']", data.mqtt.interval);
|
|
setBusy('#mqtt-settings-busy', '#mqtt-settings', false);
|
|
|
|
// Extpump
|
|
setCheckboxValue("[name='externalPump[use]']", data.externalPump.use);
|
|
setInputValue("[name='externalPump[gpio]']", data.externalPump.gpio < 255 ? data.externalPump.gpio : '');
|
|
setCheckboxValue("[name='externalPump[invertState]']", data.externalPump.invertState);
|
|
setInputValue("[name='externalPump[postCirculationTime]']", data.externalPump.postCirculationTime);
|
|
setInputValue("[name='externalPump[antiStuckInterval]']", data.externalPump.antiStuckInterval);
|
|
setInputValue("[name='externalPump[antiStuckTime]']", data.externalPump.antiStuckTime);
|
|
setBusy('#extpump-settings-busy', '#extpump-settings', false);
|
|
|
|
// Cascade control
|
|
setCheckboxValue("[name='cascadeControl[input][enabled]']", data.cascadeControl.input.enabled);
|
|
setInputValue("[name='cascadeControl[input][gpio]']", data.cascadeControl.input.gpio < 255 ? data.cascadeControl.input.gpio : '');
|
|
setCheckboxValue("[name='cascadeControl[input][invertState]']", data.cascadeControl.input.invertState);
|
|
setInputValue("[name='cascadeControl[input][thresholdTime]']", data.cascadeControl.input.thresholdTime);
|
|
|
|
setCheckboxValue("[name='cascadeControl[output][enabled]']", data.cascadeControl.output.enabled);
|
|
setInputValue("[name='cascadeControl[output][gpio]']", data.cascadeControl.output.gpio < 255 ? data.cascadeControl.output.gpio : '');
|
|
setCheckboxValue("[name='cascadeControl[output][invertState]']", data.cascadeControl.output.invertState);
|
|
setInputValue("[name='cascadeControl[output][thresholdTime]']", data.cascadeControl.output.thresholdTime);
|
|
setCheckboxValue("[name='cascadeControl[output][onFault]']", data.cascadeControl.output.onFault);
|
|
setCheckboxValue("[name='cascadeControl[output][onLossConnection]']", data.cascadeControl.output.onLossConnection);
|
|
setCheckboxValue("[name='cascadeControl[output][onEnabledHeating]']", data.cascadeControl.output.onEnabledHeating);
|
|
setBusy('#cc-settings-busy', '#cc-settings', false);
|
|
|
|
// Heating
|
|
setInputValue("[name='heating[minTemp]']", data.heating.minTemp, {
|
|
"min": data.system.unitSystem == 0 ? 0 : 32,
|
|
"max": data.system.unitSystem == 0 ? 99 : 211
|
|
});
|
|
setInputValue("[name='heating[maxTemp]']", data.heating.maxTemp, {
|
|
"min": data.system.unitSystem == 0 ? 1 : 33,
|
|
"max": data.system.unitSystem == 0 ? 100 : 212
|
|
});
|
|
setCheckboxValue("[name='heating[hysteresis][enabled]']", data.heating.hysteresis.enabled);
|
|
setInputValue("[name='heating[hysteresis][value]']", data.heating.hysteresis.value);
|
|
setSelectValue("[name='heating[hysteresis][action]']", data.heating.hysteresis.action);
|
|
setInputValue("[name='heating[turboFactor]']", data.heating.turboFactor);
|
|
setInputValue("[name='heating[maxModulation]']", data.heating.maxModulation);
|
|
setInputValue("[name='heating[overheatProtection][highTemp]']", data.heating.overheatProtection.highTemp, {
|
|
"min": 0,
|
|
"max": data.system.unitSystem == 0 ? 100 : 212
|
|
});
|
|
setInputValue("[name='heating[overheatProtection][lowTemp]']", data.heating.overheatProtection.lowTemp, {
|
|
"min": 0,
|
|
"max": data.system.unitSystem == 0 ? 99 : 211
|
|
});
|
|
setInputValue("[name='heating[freezeProtection][lowTemp]']", data.heating.freezeProtection.lowTemp, {
|
|
"min": data.system.unitSystem == 0 ? 1 : 34,
|
|
"max": data.system.unitSystem == 0 ? 30 : 86
|
|
});
|
|
setInputValue("[name='heating[freezeProtection][thresholdTime]']", data.heating.freezeProtection.thresholdTime);
|
|
setBusy('#heating-settings-busy', '#heating-settings', false);
|
|
|
|
// DHW
|
|
setInputValue("[name='dhw[minTemp]']", data.dhw.minTemp, {
|
|
"min": data.system.unitSystem == 0 ? 0 : 32,
|
|
"max": data.system.unitSystem == 0 ? 99 : 211
|
|
});
|
|
setInputValue("[name='dhw[maxTemp]']", data.dhw.maxTemp, {
|
|
"min": data.system.unitSystem == 0 ? 1 : 33,
|
|
"max": data.system.unitSystem == 0 ? 100 : 212
|
|
});
|
|
setInputValue("[name='dhw[maxModulation]']", data.dhw.maxModulation);
|
|
setInputValue("[name='dhw[overheatProtection][highTemp]']", data.dhw.overheatProtection.highTemp, {
|
|
"min": 0,
|
|
"max": data.system.unitSystem == 0 ? 100 : 212
|
|
});
|
|
setInputValue("[name='dhw[overheatProtection][lowTemp]']", data.dhw.overheatProtection.lowTemp, {
|
|
"min": 0,
|
|
"max": data.system.unitSystem == 0 ? 99 : 211
|
|
});
|
|
setBusy('#dhw-settings-busy', '#dhw-settings', false);
|
|
|
|
// Emergency mode
|
|
if (data.opentherm.options.nativeHeatingControl) {
|
|
setInputValue("[name='emergency[target]']", data.emergency.target, {
|
|
"min": data.system.unitSystem == 0 ? 5 : 41,
|
|
"max": data.system.unitSystem == 0 ? 40 : 104
|
|
});
|
|
|
|
} else {
|
|
setInputValue("[name='emergency[target]']", data.emergency.target, {
|
|
"min": data.heating.minTemp,
|
|
"max": data.heating.maxTemp,
|
|
});
|
|
}
|
|
setInputValue("[name='emergency[tresholdTime]']", data.emergency.tresholdTime);
|
|
setBusy('#emergency-settings-busy', '#emergency-settings', false);
|
|
|
|
// Equitherm
|
|
setCheckboxValue("[name='equitherm[enabled]']", data.equitherm.enabled);
|
|
setInputValue("[name='equitherm[slope]']", data.equitherm.slope);
|
|
setInputValue("[name='equitherm[exponent]']", data.equitherm.exponent);
|
|
setInputValue("[name='equitherm[shift]']", data.equitherm.shift);
|
|
setInputValue("[name='equitherm[targetDiffFactor]']", data.equitherm.targetDiffFactor);
|
|
setBusy('#equitherm-settings-busy', '#equitherm-settings', false);
|
|
|
|
// PID
|
|
setCheckboxValue("[name='pid[enabled]']", data.pid.enabled);
|
|
setInputValue("[name='pid[p_factor]']", data.pid.p_factor);
|
|
setInputValue("[name='pid[i_factor]']", data.pid.i_factor);
|
|
setInputValue("[name='pid[d_factor]']", data.pid.d_factor);
|
|
setInputValue("[name='pid[dt]']", data.pid.dt);
|
|
setInputValue("[name='pid[minTemp]']", data.pid.minTemp, {
|
|
"min": data.equitherm.enabled ? (data.system.unitSystem == 0 ? -100 : -146) : (data.system.unitSystem == 0 ? 0 : 32),
|
|
"max": (data.system.unitSystem == 0 ? 99 : 211)
|
|
});
|
|
setInputValue("[name='pid[maxTemp]']", data.pid.maxTemp, {
|
|
"min": (data.system.unitSystem == 0 ? 0 : 33),
|
|
"max": (data.system.unitSystem == 0 ? 100 : 212)
|
|
});
|
|
setCheckboxValue("[name='pid[deadband][enabled]']", data.pid.deadband.enabled);
|
|
setInputValue("[name='pid[deadband][p_multiplier]']", data.pid.deadband.p_multiplier);
|
|
setInputValue("[name='pid[deadband][i_multiplier]']", data.pid.deadband.i_multiplier);
|
|
setInputValue("[name='pid[deadband][d_multiplier]']", data.pid.deadband.d_multiplier);
|
|
setInputValue("[name='pid[deadband][thresholdHigh]']", data.pid.deadband.thresholdHigh);
|
|
setInputValue("[name='pid[deadband][thresholdLow]']", data.pid.deadband.thresholdLow);
|
|
setBusy('#pid-settings-busy', '#pid-settings', false);
|
|
|
|
const etMinTemp = parseInt(data.system.unitSystem == 0 ? 5 : 41);
|
|
const etMaxTemp = parseInt(data.system.unitSystem == 0 ? 30 : 86);
|
|
const etTargetTemp = constrain(parseFloat(data.heating.target), etMinTemp, etMaxTemp);
|
|
|
|
setInputValue(".etChartTargetTemp", etTargetTemp.toFixed(1), {
|
|
"min": etMinTemp,
|
|
"max": etMaxTemp
|
|
});
|
|
|
|
etChartConfig.slope = data.equitherm.slope;
|
|
etChartConfig.exponent = data.equitherm.exponent;
|
|
etChartConfig.shift = data.equitherm.shift;
|
|
etChartConfig.unitSystem = data.system.unitSystem;
|
|
etChartConfig.minTemp = data.heating.minTemp;
|
|
etChartConfig.maxTemp = data.heating.maxTemp;
|
|
|
|
makeEquithermChart();
|
|
};
|
|
|
|
try {
|
|
const response = await fetch("/static/timezones.json");
|
|
if (!response.ok) {
|
|
throw new Error('Response not valid');
|
|
}
|
|
|
|
const result = await response.json();
|
|
const ptzSelector = document.querySelector(".presetTimezones");
|
|
for (const ptzName in result) {
|
|
ptzSelector.appendChild(
|
|
new Option(ptzName, result[ptzName])
|
|
);
|
|
}
|
|
|
|
ptzSelector.addEventListener("change", async (event) => {
|
|
document.querySelector("[name='system[ntp][timezone]']").value = event.target.value;
|
|
});
|
|
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
|
|
try {
|
|
const response = await fetch("/api/settings", {
|
|
cache: "no-cache",
|
|
credentials: "include"
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error('Response not valid');
|
|
}
|
|
|
|
const result = await response.json();
|
|
fillData(result);
|
|
|
|
setupForm('#portal-settings', fillData, ['portal.login', 'portal.password']);
|
|
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('#ot-settings', fillData);
|
|
setupForm('#mqtt-settings', fillData, ['mqtt.user', 'mqtt.password', 'mqtt.prefix']);
|
|
setupForm('#extpump-settings', fillData);
|
|
setupForm('#cc-settings', fillData);
|
|
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
|
|
document.querySelector(".etChartTargetTemp").addEventListener("input", async (event) => {
|
|
setValue('.etChartTargetTempValue', parseFloat(event.target.value).toFixed(1));
|
|
});
|
|
|
|
document.querySelector(".etChartTargetTemp").addEventListener("change", async (event) => {
|
|
if (!event.target.checkValidity()) {
|
|
return;
|
|
}
|
|
|
|
etChartConfig.targetTemp = parseFloat(event.target.value);
|
|
setValue('.etChartTargetTempValue', etChartConfig.targetTemp.toFixed(1));
|
|
makeEquithermChart();
|
|
});
|
|
|
|
document.querySelector("[name='equitherm[slope]']").addEventListener("change", async (event) => {
|
|
if (!event.target.checkValidity()) {
|
|
return;
|
|
}
|
|
|
|
etChartConfig.slope = parseFloat(event.target.value);
|
|
makeEquithermChart();
|
|
});
|
|
|
|
document.querySelector("[name='equitherm[exponent]']").addEventListener("change", async (event) => {
|
|
if (!event.target.checkValidity()) {
|
|
return;
|
|
}
|
|
|
|
etChartConfig.exponent = parseFloat(event.target.value);
|
|
makeEquithermChart();
|
|
});
|
|
|
|
document.querySelector("[name='equitherm[shift]']").addEventListener("change", async (event) => {
|
|
if (!event.target.checkValidity()) {
|
|
return;
|
|
}
|
|
|
|
etChartConfig.shift = parseFloat(event.target.value);
|
|
makeEquithermChart();
|
|
});
|
|
|
|
window.addEventListener('resize', async (event) => {
|
|
if (etChart) {
|
|
etChart.resize();
|
|
|
|
if (etChartConfig.decimated != hasNeedDecimationChart()) {
|
|
makeEquithermChart();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |