Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7f3c66e05 | ||
|
|
17bd31b2a2 | ||
|
|
8662b9dc8f | ||
|
|
6efa3a52fe | ||
|
|
7e31de6c71 | ||
|
|
b53dae6a43 | ||
|
|
de2318bc6a | ||
|
|
081209420a | ||
|
|
75bc4d5c4a | ||
|
|
527e9cc1d6 | ||
|
|
60b7caf4bc | ||
|
|
e8d0ad0a4e | ||
|
|
afe269aeff | ||
|
|
4702909043 | ||
|
|
4c32ccc450 | ||
|
|
2e3b38e14f | ||
|
|
b6c80f355f | ||
|
|
65b2a3c2bd | ||
|
|
0cb361d243 | ||
|
|
c7f54ca4fb | ||
|
|
1d46176b5e | ||
|
|
5e2f6c9cea | ||
|
|
f439f8c5ba | ||
|
|
bae7770371 | ||
|
|
4e5a3e9da5 | ||
|
|
412e1594e9 | ||
|
|
9701e8c97b | ||
|
|
2fe546812c |
68
README.md
@@ -1,40 +1,44 @@
|
||||
<div align="center">
|
||||
|
||||

|
||||
<br>
|
||||
|
||||
[](https://github.com/Laxilef/OTGateway/releases)
|
||||
[](https://github.com/Laxilef/OTGateway/releases/latest)
|
||||
[](LICENSE.txt)
|
||||
[](https://t.me/otgateway)
|
||||
|
||||
|
||||
</div>
|
||||
<hr />
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
## Features
|
||||
- Hot water temperature control
|
||||
- DHW temperature control
|
||||
- Heating temperature control
|
||||
- Smart heating temperature control modes:
|
||||
- PID
|
||||
- Equithermic curves - adjusts the temperature based on indoor and outdoor temperatures
|
||||
- Hysteresis setting (for accurate maintenance of room temperature)
|
||||
- Ability to connect an external sensors to monitor outdoor and indoor temperature ([compatible sensors](https://github.com/Laxilef/OTGateway/wiki/Compatibility#temperature-sensors))
|
||||
- Emergency mode. If the Wi-Fi connection is lost or the gateway cannot connect to the MQTT server, the mode will turn on. This mode will automatically maintain the set temperature and prevent your home from freezing. In this mode it is also possible to use equithermal curves (weather-compensated control).
|
||||
- Automatic error reset (not with all boilers)
|
||||
- Hysteresis setting _(for accurate maintenance of room temperature)_
|
||||
- Ability to connect [additional (external) sensors](https://github.com/Laxilef/OTGateway/wiki/Compatibility#temperature-sensors): Dallas (1-wire), NTC 10k, Bluetooth (BLE). Makes it possible to monitor indoor and outdoor temperatures, temperatures on pipes/heat exchangers/etc.
|
||||
- Emergency mode. In any dangerous situation _(loss of connection with Wifi, MQTT, sensors, etc)_ it will not let you and your home freeze.
|
||||
- Ability of remote fault reset _(not with all boilers)_
|
||||
- Diagnostics:
|
||||
- The process of heating: works/does not work
|
||||
- The process of heating water for hot water: working/not working
|
||||
- Display of boiler errors
|
||||
- Burner status (flame): on/off
|
||||
- Burner modulation level in percent
|
||||
- Pressure in the heating system
|
||||
- Gateway status (depending on errors and connection status)
|
||||
- Boiler connection status via OpenTherm interface
|
||||
- The current temperature of the heat carrier (usually the return heat carrier)
|
||||
- Set heat carrier temperature (depending on the selected mode)
|
||||
- Current hot water temperature
|
||||
- Displaying gateway status
|
||||
- Displaying the connection status to the boiler via OpenTherm
|
||||
- Displaying the fault status and fault code
|
||||
- Displaying the diagnostic status & diagnostic code
|
||||
- Display of the process of heating: works/does not work
|
||||
- Display of burner (flame) status: on/off
|
||||
- Display of burner modulation level in percent
|
||||
- Display of pressure in the heating system
|
||||
- Display of current temperature of the heat carrier
|
||||
- Display of return temperature of the heat carrier
|
||||
- Display of setpoint heat carrier temperature (useful when using PID or Equitherm)
|
||||
- Display of the process of DHW: working/not working
|
||||
- Display of current DHW temperature
|
||||
- _And other information..._
|
||||
- [Home Assistant](https://www.home-assistant.io/) integration via MQTT. The ability to create any automation for the boiler!
|
||||
|
||||

|
||||
|
||||
## Documentation
|
||||
All available information and instructions can be found in the wiki:
|
||||
|
||||
@@ -52,6 +56,7 @@ All available information and instructions can be found in the wiki:
|
||||
* [Ratios](https://github.com/Laxilef/OTGateway/wiki#ratios)
|
||||
* [Fit coefficients](https://github.com/Laxilef/OTGateway/wiki#fit-coefficients)
|
||||
* [PID mode](https://github.com/Laxilef/OTGateway/wiki#pid-mode)
|
||||
* [Logs and debug](https://github.com/Laxilef/OTGateway/wiki#logs-and-debug)
|
||||
* [Compatibility](https://github.com/Laxilef/OTGateway/wiki/Compatibility)
|
||||
* [Boilers](https://github.com/Laxilef/OTGateway/wiki/Compatibility#boilers)
|
||||
* [Boards](https://github.com/Laxilef/OTGateway/wiki/Compatibility#boards)
|
||||
@@ -64,24 +69,5 @@ All available information and instructions can be found in the wiki:
|
||||
* [Connection](https://github.com/Laxilef/OTGateway/wiki/OT-adapters#connection)
|
||||
* [Leds on board](https://github.com/Laxilef/OTGateway/wiki/OT-adapters#leds-on-board)
|
||||
|
||||
|
||||
|
||||
## Dependencies
|
||||
- [ESP8266Scheduler](https://github.com/nrwiersma/ESP8266Scheduler) (for ESP8266)
|
||||
- [ESP32Scheduler](https://github.com/laxilef/ESP32Scheduler) (for ESP32)
|
||||
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson)
|
||||
- [OpenTherm Library](https://github.com/ihormelnyk/opentherm_library)
|
||||
- [ArduinoMqttClient](https://github.com/arduino-libraries/ArduinoMqttClient)
|
||||
- [ESPTelnet](https://github.com/LennartHennigs/ESPTelnet)
|
||||
- [FileData](https://github.com/GyverLibs/FileData)
|
||||
- [GyverPID](https://github.com/GyverLibs/GyverPID)
|
||||
- [GyverBlinker](https://github.com/GyverLibs/GyverBlinker)
|
||||
- [DallasTemperature](https://github.com/milesburton/Arduino-Temperature-Control-Library)
|
||||
- [TinyLogger](https://github.com/laxilef/TinyLogger)
|
||||
|
||||
## Debug
|
||||
To display DEBUG messages you must enable debug in settings (switch is disabled by default).
|
||||
You can connect via Telnet to read messages. IP: ESP8266 ip, port: 23
|
||||
|
||||
___
|
||||
This project is tested with BrowserStack.
|
||||
|
||||
|
Before Width: | Height: | Size: 261 KiB After Width: | Height: | Size: 283 KiB |
|
Before Width: | Height: | Size: 326 KiB After Width: | Height: | Size: 386 KiB |
|
Before Width: | Height: | Size: 684 KiB After Width: | Height: | Size: 849 KiB |
BIN
assets/BOM.xlsx
BIN
assets/CPL.csv
22697
assets/Schematic.pdf
BIN
assets/ha.png
|
Before Width: | Height: | Size: 190 KiB |
BIN
assets/poster-1.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
assets/poster-2.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
assets/poster-3.png
Normal file
|
After Width: | Height: | Size: 973 KiB |
@@ -12,16 +12,17 @@ public:
|
||||
|
||||
template <class T>
|
||||
void send(int code, T contentType, const JsonVariantConst content, bool pretty = false) {
|
||||
auto contentLength = pretty ? measureJsonPretty(content) : measureJson(content);
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
if (!this->webServer->chunkedResponseModeStart(code, contentType)) {
|
||||
this->webServer->send(505, F("text/html"), F("HTTP1.1 required"));
|
||||
return;
|
||||
}
|
||||
|
||||
this->webServer->setContentLength(measureJson(content));
|
||||
this->webServer->setContentLength(contentLength);
|
||||
#else
|
||||
this->webServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
this->webServer->sendHeader(F("Content-Length"), String(measureJson(content)));
|
||||
this->webServer->setContentLength(contentLength);
|
||||
this->webServer->send(code, contentType, emptyString);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,15 +3,17 @@
|
||||
|
||||
class CustomOpenTherm : public OpenTherm {
|
||||
public:
|
||||
typedef std::function<void()> YieldCallback;
|
||||
typedef std::function<void(unsigned int)> DelayCallback;
|
||||
typedef std::function<void(unsigned long, byte)> BeforeSendRequestCallback;
|
||||
typedef std::function<void(unsigned long, unsigned long, OpenThermResponseStatus, byte)> AfterSendRequestCallback;
|
||||
|
||||
CustomOpenTherm(int inPin = 4, int outPin = 5, bool isSlave = false) : OpenTherm(inPin, outPin, isSlave) {}
|
||||
CustomOpenTherm(int inPin = 4, int outPin = 5, bool isSlave = false) : OpenTherm(inPin, outPin, isSlave) {
|
||||
this->_outPin = outPin;
|
||||
}
|
||||
~CustomOpenTherm() {}
|
||||
|
||||
CustomOpenTherm* setYieldCallback(YieldCallback callback = nullptr) {
|
||||
this->yieldCallback = callback;
|
||||
CustomOpenTherm* setDelayCallback(DelayCallback callback = nullptr) {
|
||||
this->delayCallback = callback;
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -28,14 +30,28 @@ public:
|
||||
return this;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if (this->status == OpenThermStatus::NOT_INITIALIZED) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->end();
|
||||
this->status = OpenThermStatus::NOT_INITIALIZED;
|
||||
|
||||
digitalWrite(this->_outPin, LOW);
|
||||
if (this->delayCallback) {
|
||||
this->delayCallback(1000);
|
||||
}
|
||||
|
||||
this->begin();
|
||||
}
|
||||
|
||||
unsigned long sendRequest(unsigned long request, byte attempts = 5, byte _attempt = 0) {
|
||||
_attempt++;
|
||||
|
||||
while (!this->isReady()) {
|
||||
if (this->yieldCallback) {
|
||||
this->yieldCallback();
|
||||
} else {
|
||||
::yield();
|
||||
if (this->delayCallback) {
|
||||
this->delayCallback(150);
|
||||
}
|
||||
|
||||
this->process();
|
||||
@@ -51,17 +67,13 @@ public:
|
||||
_response = 0;
|
||||
|
||||
} else {
|
||||
while (true) {
|
||||
this->process();
|
||||
|
||||
if (this->status == OpenThermStatus::READY || this->status == OpenThermStatus::DELAY) {
|
||||
break;
|
||||
} else if (this->yieldCallback) {
|
||||
this->yieldCallback();
|
||||
} else {
|
||||
::yield();
|
||||
do {
|
||||
if (this->delayCallback) {
|
||||
this->delayCallback(150);
|
||||
}
|
||||
}
|
||||
|
||||
this->process();
|
||||
} while (this->status != OpenThermStatus::READY && this->status != OpenThermStatus::DELAY);
|
||||
|
||||
_response = this->getLastResponse();
|
||||
_responseStatus = this->getLastResponseStatus();
|
||||
@@ -151,7 +163,8 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
YieldCallback yieldCallback;
|
||||
DelayCallback delayCallback;
|
||||
BeforeSendRequestCallback beforeSendRequestCallback;
|
||||
AfterSendRequestCallback afterSendRequestCallback;
|
||||
int _outPin;
|
||||
};
|
||||
|
||||
@@ -14,10 +14,10 @@ extra_configs = secrets.default.ini
|
||||
core_dir = .pio
|
||||
|
||||
[env]
|
||||
version = 1.5.0
|
||||
version = 1.5.1
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson@^7.1.0
|
||||
bblanchon/ArduinoJson@^7.3.0
|
||||
;ihormelnyk/OpenTherm Library@^1.1.5
|
||||
https://github.com/ihormelnyk/opentherm_library#master
|
||||
;arduino-libraries/ArduinoMqttClient@^0.1.8
|
||||
@@ -85,13 +85,13 @@ board_build.ldscript = eagle.flash.4m1m.ld
|
||||
;platform_packages =
|
||||
; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.5
|
||||
; framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-33fbade6.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10/platform-espressif32.zip
|
||||
platform_packages =
|
||||
board_build.partitions = esp32_partitions.csv
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
laxilef/ESP32Scheduler@^1.0.1
|
||||
nimble_lib = h2zero/NimBLE-Arduino@^1.4.2
|
||||
nimble_lib = h2zero/NimBLE-Arduino@^2.1.0
|
||||
lib_ignore =
|
||||
extra_scripts =
|
||||
post:tools/esp32.py
|
||||
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
if (sSensor.type == Sensors::Type::BLUETOOTH) {
|
||||
// available state topic
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = doc[FPSTR(HA_STATE_TOPIC)];
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_SENSOR_CONN;
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_SENSOR_CONN, true);
|
||||
|
||||
String sName = sSensor.name;
|
||||
switch (vType) {
|
||||
@@ -254,7 +254,7 @@ public:
|
||||
} else {
|
||||
// available state topic
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = doc[FPSTR(HA_STATE_TOPIC)];
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_SENSOR_CONN;
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_SENSOR_CONN, true);
|
||||
|
||||
doc[FPSTR(HA_NAME)] = sSensor.name;
|
||||
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.value|float(0)|round(2) }}");
|
||||
@@ -970,7 +970,7 @@ public:
|
||||
JsonDocument doc;
|
||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_OT_CONN;
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_OT_CONN, true);
|
||||
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
|
||||
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating"));
|
||||
@@ -991,7 +991,7 @@ public:
|
||||
JsonDocument doc;
|
||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_OT_CONN;
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_OT_CONN, true);
|
||||
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
|
||||
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw"));
|
||||
@@ -1012,7 +1012,7 @@ public:
|
||||
JsonDocument doc;
|
||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_OT_CONN;
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_OT_CONN, true);
|
||||
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
|
||||
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("flame"));
|
||||
@@ -1033,7 +1033,7 @@ public:
|
||||
JsonDocument doc;
|
||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_OT_CONN;
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_OT_CONN, true);
|
||||
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
|
||||
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("fault"));
|
||||
@@ -1054,7 +1054,7 @@ public:
|
||||
JsonDocument doc;
|
||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_OT_CONN;
|
||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_OT_CONN, true);
|
||||
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
|
||||
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC));
|
||||
|
||||
@@ -229,7 +229,7 @@ protected:
|
||||
emergencyFlags |= 0b00000010;
|
||||
}
|
||||
|
||||
if (settings.opentherm.nativeHeatingControl) {
|
||||
if (settings.opentherm.options.nativeHeatingControl) {
|
||||
emergencyFlags |= 0b00000100;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,13 +532,13 @@ protected:
|
||||
|
||||
bool publishNonStaticHaEntities(bool force = false) {
|
||||
static byte _heatingMinTemp, _heatingMaxTemp, _dhwMinTemp, _dhwMaxTemp = 0;
|
||||
static bool _indoorTempControl, _dhwPresent = false;
|
||||
static bool _indoorTempControl, _dhwSupport = false;
|
||||
|
||||
bool published = false;
|
||||
if (force || _dhwPresent != settings.opentherm.dhwPresent) {
|
||||
_dhwPresent = settings.opentherm.dhwPresent;
|
||||
if (force || _dhwSupport != settings.opentherm.options.dhwSupport) {
|
||||
_dhwSupport = settings.opentherm.options.dhwSupport;
|
||||
|
||||
if (_dhwPresent) {
|
||||
if (_dhwSupport) {
|
||||
this->haHelper->publishInputDhwMinTemp(settings.system.unitSystem);
|
||||
this->haHelper->publishInputDhwMaxTemp(settings.system.unitSystem);
|
||||
this->haHelper->publishDhwState();
|
||||
@@ -569,7 +569,7 @@ protected:
|
||||
published = true;
|
||||
}
|
||||
|
||||
if (_dhwPresent && (force || _dhwMinTemp != settings.dhw.minTemp || _dhwMaxTemp != settings.dhw.maxTemp)) {
|
||||
if (_dhwSupport && (force || _dhwMinTemp != settings.dhw.minTemp || _dhwMaxTemp != settings.dhw.maxTemp)) {
|
||||
_dhwMinTemp = settings.dhw.minTemp;
|
||||
_dhwMaxTemp = settings.dhw.maxTemp;
|
||||
|
||||
|
||||
@@ -98,8 +98,8 @@ protected:
|
||||
}
|
||||
});
|
||||
|
||||
this->instance->setYieldCallback([this]() {
|
||||
this->delay(25);
|
||||
this->instance->setDelayCallback([this](unsigned int time) {
|
||||
this->delay(time);
|
||||
});
|
||||
|
||||
this->instance->begin();
|
||||
@@ -153,18 +153,18 @@ protected:
|
||||
&& !vars.master.heating.blocking;
|
||||
|
||||
// DHW settings
|
||||
vars.master.dhw.enabled = settings.opentherm.dhwPresent && settings.dhw.enabled;
|
||||
vars.master.dhw.enabled = settings.opentherm.options.dhwSupport && settings.dhw.enabled;
|
||||
vars.master.dhw.targetTemp = settings.dhw.target;
|
||||
|
||||
// CH2 settings
|
||||
vars.master.ch2.enabled = settings.opentherm.heatingCh2Enabled
|
||||
|| (settings.opentherm.heatingCh1ToCh2 && vars.master.heating.enabled)
|
||||
|| (settings.opentherm.dhwToCh2 && settings.opentherm.dhwPresent && settings.dhw.enabled);
|
||||
vars.master.ch2.enabled = settings.opentherm.options.ch2AlwaysEnabled
|
||||
|| (settings.opentherm.options.heatingToCh2 && vars.master.heating.enabled)
|
||||
|| (settings.opentherm.options.dhwToCh2 && settings.opentherm.options.dhwSupport && settings.dhw.enabled);
|
||||
|
||||
if (settings.opentherm.heatingCh1ToCh2) {
|
||||
if (settings.opentherm.options.heatingToCh2) {
|
||||
vars.master.ch2.targetTemp = vars.master.heating.setpointTemp;
|
||||
|
||||
} else if (settings.opentherm.dhwToCh2) {
|
||||
} else if (settings.opentherm.options.dhwToCh2) {
|
||||
vars.master.ch2.targetTemp = vars.master.dhw.targetTemp;
|
||||
}
|
||||
|
||||
@@ -174,18 +174,24 @@ protected:
|
||||
|
||||
// Immergas fix
|
||||
// https://arduino.ru/forum/programmirovanie/termostat-opentherm-na-esp8266?page=15#comment-649392
|
||||
if (settings.opentherm.immergasFix) {
|
||||
if (settings.opentherm.options.immergasFix) {
|
||||
statusLb = 0xCA;
|
||||
}
|
||||
|
||||
// Summer/winter mode
|
||||
bool summerWinterMode = settings.opentherm.options.summerWinterMode;
|
||||
if (settings.opentherm.options.heatingStateToSummerWinterMode) {
|
||||
summerWinterMode = vars.master.heating.enabled == summerWinterMode;
|
||||
}
|
||||
|
||||
unsigned long response = this->instance->setBoilerStatus(
|
||||
vars.master.heating.enabled,
|
||||
vars.master.dhw.enabled,
|
||||
false,
|
||||
settings.opentherm.nativeHeatingControl,
|
||||
settings.opentherm.options.coolingSupport,
|
||||
settings.opentherm.options.nativeHeatingControl,
|
||||
vars.master.ch2.enabled,
|
||||
settings.opentherm.summerWinterMode,
|
||||
settings.opentherm.dhwBlocking,
|
||||
summerWinterMode,
|
||||
settings.opentherm.options.dhwBlocking,
|
||||
statusLb
|
||||
);
|
||||
|
||||
@@ -197,12 +203,12 @@ protected:
|
||||
);
|
||||
}
|
||||
|
||||
if (!vars.slave.connected && millis() - this->lastSuccessResponse < 1150) {
|
||||
if (!vars.slave.connected && millis() - this->lastSuccessResponse < 1325) {
|
||||
Log.sinfoln(FPSTR(L_OT), F("Connected"));
|
||||
|
||||
vars.slave.connected = true;
|
||||
|
||||
} else if (vars.slave.connected && millis() - this->lastSuccessResponse > 1150) {
|
||||
} else if (vars.slave.connected && millis() - this->lastSuccessResponse > 1325) {
|
||||
Log.swarningln(FPSTR(L_OT), F("Disconnected"));
|
||||
|
||||
// Mark sensors as disconnected
|
||||
@@ -242,6 +248,8 @@ protected:
|
||||
vars.slave.diag.active = false;
|
||||
vars.slave.diag.code = 0;
|
||||
|
||||
this->instance->reset();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -265,15 +273,16 @@ protected:
|
||||
}
|
||||
|
||||
vars.slave.heating.active = CustomOpenTherm::isCentralHeatingActive(response);
|
||||
vars.slave.dhw.active = settings.opentherm.dhwPresent ? CustomOpenTherm::isHotWaterActive(response) : false;
|
||||
vars.slave.dhw.active = settings.opentherm.options.dhwSupport ? CustomOpenTherm::isHotWaterActive(response) : false;
|
||||
vars.slave.flame = CustomOpenTherm::isFlameOn(response);
|
||||
vars.slave.cooling = CustomOpenTherm::isCoolingActive(response);
|
||||
vars.slave.fault.active = CustomOpenTherm::isFault(response);
|
||||
vars.slave.diag.active = CustomOpenTherm::isDiagnostic(response);
|
||||
|
||||
Log.snoticeln(
|
||||
FPSTR(L_OT), F("Received boiler status. Heating: %hhu; DHW: %hhu; flame: %hhu; fault: %hhu; diag: %hhu"),
|
||||
FPSTR(L_OT), F("Received boiler status. Heating: %hhu; DHW: %hhu; flame: %hhu; cooling: %hhu; fault: %hhu; diag: %hhu"),
|
||||
vars.slave.heating.active, vars.slave.dhw.active,
|
||||
vars.slave.flame, vars.slave.fault.active, vars.slave.diag.active
|
||||
vars.slave.flame, vars.slave.cooling, vars.slave.fault.active, vars.slave.diag.active
|
||||
);
|
||||
|
||||
// These parameters will be updated every minute
|
||||
@@ -309,7 +318,7 @@ protected:
|
||||
Log.swarningln(FPSTR(L_OT), F("Failed receive min modulation and max power"));
|
||||
}
|
||||
|
||||
if (!vars.master.heating.enabled && settings.opentherm.modulationSyncWithHeating) {
|
||||
if (!vars.master.heating.enabled && settings.opentherm.options.modulationSyncWithHeating) {
|
||||
if (this->setMaxModulationLevel(0)) {
|
||||
Log.snoticeln(FPSTR(L_OT), F("Set max modulation: 0% (response: %hhu%%)"), vars.slave.modulation.max);
|
||||
|
||||
@@ -334,7 +343,7 @@ protected:
|
||||
|
||||
|
||||
// Get DHW min/max temp (if necessary)
|
||||
if (settings.opentherm.dhwPresent && settings.opentherm.getMinMaxTemp) {
|
||||
if (settings.opentherm.options.dhwSupport && settings.opentherm.options.getMinMaxTemp) {
|
||||
if (this->updateMinMaxDhwTemp()) {
|
||||
uint8_t convertedMinTemp = convertTemp(
|
||||
vars.slave.dhw.minTemp,
|
||||
@@ -380,7 +389,7 @@ protected:
|
||||
|
||||
|
||||
// Get heating min/max temp
|
||||
if (settings.opentherm.getMinMaxTemp) {
|
||||
if (settings.opentherm.options.getMinMaxTemp) {
|
||||
if (this->updateMinMaxHeatingTemp()) {
|
||||
uint8_t convertedMinTemp = convertTemp(
|
||||
vars.slave.heating.minTemp,
|
||||
@@ -520,7 +529,7 @@ protected:
|
||||
}
|
||||
|
||||
// Update DHW temp
|
||||
if (settings.opentherm.dhwPresent && Sensors::getAmountByType(Sensors::Type::OT_DHW_TEMP, true)) {
|
||||
if (settings.opentherm.options.dhwSupport && Sensors::getAmountByType(Sensors::Type::OT_DHW_TEMP, true)) {
|
||||
bool result = this->updateDhwTemp();
|
||||
|
||||
if (result) {
|
||||
@@ -546,7 +555,7 @@ protected:
|
||||
}
|
||||
|
||||
// Update DHW temp 2
|
||||
if (settings.opentherm.dhwPresent && Sensors::getAmountByType(Sensors::Type::OT_DHW_TEMP2, true)) {
|
||||
if (settings.opentherm.options.dhwSupport && Sensors::getAmountByType(Sensors::Type::OT_DHW_TEMP2, true)) {
|
||||
if (this->updateDhwTemp2()) {
|
||||
float convertedDhwTemp2 = convertTemp(
|
||||
vars.slave.dhw.currentTemp2,
|
||||
@@ -570,7 +579,7 @@ protected:
|
||||
}
|
||||
|
||||
// Update DHW flow rate
|
||||
if (settings.opentherm.dhwPresent && Sensors::getAmountByType(Sensors::Type::OT_DHW_FLOW_RATE, true)) {
|
||||
if (settings.opentherm.options.dhwSupport && Sensors::getAmountByType(Sensors::Type::OT_DHW_FLOW_RATE, true)) {
|
||||
if (this->updateDhwFlowRate()) {
|
||||
float convertedDhwFlowRate = convertVolume(
|
||||
vars.slave.dhw.flowRate,
|
||||
@@ -643,7 +652,7 @@ protected:
|
||||
|
||||
// Update CH2 temp
|
||||
if (Sensors::getAmountByType(Sensors::Type::OT_CH2_TEMP, true)) {
|
||||
if (vars.master.ch2.enabled && !settings.opentherm.nativeHeatingControl) {
|
||||
if (vars.master.ch2.enabled && !settings.opentherm.options.nativeHeatingControl) {
|
||||
if (this->updateCh2Temp()) {
|
||||
float convertedCh2Temp = convertTemp(
|
||||
vars.slave.ch2.currentTemp,
|
||||
@@ -942,7 +951,7 @@ protected:
|
||||
}
|
||||
|
||||
// Native heating control
|
||||
if (settings.opentherm.nativeHeatingControl) {
|
||||
if (settings.opentherm.options.nativeHeatingControl) {
|
||||
// Converted current indoor temp
|
||||
float convertedTemp = convertTemp(vars.master.heating.indoorTemp, settings.system.unitSystem, settings.opentherm.unitSystem);
|
||||
|
||||
@@ -958,7 +967,7 @@ protected:
|
||||
}
|
||||
|
||||
// Set current CH2 indoor temp
|
||||
if (settings.opentherm.heatingCh1ToCh2) {
|
||||
if (settings.opentherm.options.heatingToCh2) {
|
||||
if (this->setRoomTempCh2(convertedTemp)) {
|
||||
Log.sinfoln(
|
||||
FPSTR(L_OT_HEATING), F("Set current CH2 indoor temp: %.2f (converted: %.2f, response: %.2f)"),
|
||||
@@ -990,7 +999,7 @@ protected:
|
||||
}
|
||||
|
||||
// Set target CH2 temp
|
||||
if (settings.opentherm.heatingCh1ToCh2 && this->needSetCh2Temp(convertedTemp)) {
|
||||
if (settings.opentherm.options.heatingToCh2 && this->needSetCh2Temp(convertedTemp)) {
|
||||
if (this->setRoomSetpointCh2(convertedTemp)) {
|
||||
this->ch2SetTempTime = millis();
|
||||
|
||||
@@ -1006,20 +1015,22 @@ protected:
|
||||
}
|
||||
|
||||
// Normal heating control
|
||||
if (!settings.opentherm.nativeHeatingControl && vars.master.heating.enabled) {
|
||||
if (!settings.opentherm.options.nativeHeatingControl && vars.master.heating.enabled) {
|
||||
// Converted target heating temp
|
||||
float convertedTemp = convertTemp(vars.master.heating.setpointTemp, settings.system.unitSystem, settings.opentherm.unitSystem);
|
||||
|
||||
if (this->needSetHeatingTemp(convertedTemp)) {
|
||||
// Set max heating temp
|
||||
if (this->setMaxHeatingTemp(convertedTemp)) {
|
||||
Log.sinfoln(
|
||||
FPSTR(L_OT_HEATING), F("Set max heating temp: %.2f (converted: %.2f)"),
|
||||
vars.master.heating.setpointTemp, convertedTemp
|
||||
);
|
||||
if (settings.opentherm.options.maxTempSyncWithTargetTemp) {
|
||||
if (this->setMaxHeatingTemp(convertedTemp)) {
|
||||
Log.sinfoln(
|
||||
FPSTR(L_OT_HEATING), F("Set max heating temp: %.2f (converted: %.2f)"),
|
||||
vars.master.heating.setpointTemp, convertedTemp
|
||||
);
|
||||
|
||||
} else {
|
||||
Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set max heating temp"));
|
||||
} else {
|
||||
Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set max heating temp"));
|
||||
}
|
||||
}
|
||||
|
||||
// Set target heating temp
|
||||
@@ -1038,8 +1049,8 @@ protected:
|
||||
}
|
||||
|
||||
// Set CH2 temp
|
||||
if (!settings.opentherm.nativeHeatingControl && vars.master.ch2.enabled) {
|
||||
if (settings.opentherm.heatingCh1ToCh2 || settings.opentherm.dhwToCh2) {
|
||||
if (!settings.opentherm.options.nativeHeatingControl && vars.master.ch2.enabled) {
|
||||
if (settings.opentherm.options.heatingToCh2 || settings.opentherm.options.dhwToCh2) {
|
||||
// Converted target CH2 temp
|
||||
float convertedTemp = convertTemp(
|
||||
vars.master.ch2.targetTemp,
|
||||
|
||||
@@ -39,7 +39,7 @@ protected:
|
||||
this->indoorSensorsConnected = Sensors::existsConnectedSensorsByPurpose(Sensors::Purpose::INDOOR_TEMP);
|
||||
//this->outdoorSensorsConnected = Sensors::existsConnectedSensorsByPurpose(Sensors::Purpose::OUTDOOR_TEMP);
|
||||
|
||||
if (settings.equitherm.enabled || settings.pid.enabled || settings.opentherm.nativeHeatingControl) {
|
||||
if (settings.equitherm.enabled || settings.pid.enabled || settings.opentherm.options.nativeHeatingControl) {
|
||||
vars.master.heating.indoorTempControl = true;
|
||||
vars.master.heating.minTemp = THERMOSTAT_INDOOR_MIN_TEMP;
|
||||
vars.master.heating.maxTemp = THERMOSTAT_INDOOR_MAX_TEMP;
|
||||
@@ -93,7 +93,7 @@ protected:
|
||||
void hysteresis() {
|
||||
bool useHyst = false;
|
||||
if (settings.heating.hysteresis > 0.01f && this->indoorSensorsConnected) {
|
||||
useHyst = settings.equitherm.enabled || settings.pid.enabled || settings.opentherm.nativeHeatingControl;
|
||||
useHyst = settings.equitherm.enabled || settings.pid.enabled || settings.opentherm.options.nativeHeatingControl;
|
||||
}
|
||||
|
||||
if (useHyst) {
|
||||
@@ -110,13 +110,13 @@ protected:
|
||||
}
|
||||
|
||||
inline float getHeatingMinSetpointTemp() {
|
||||
return settings.opentherm.nativeHeatingControl
|
||||
return settings.opentherm.options.nativeHeatingControl
|
||||
? vars.master.heating.minTemp
|
||||
: settings.heating.minTemp;
|
||||
}
|
||||
|
||||
inline float getHeatingMaxSetpointTemp() {
|
||||
return settings.opentherm.nativeHeatingControl
|
||||
return settings.opentherm.options.nativeHeatingControl
|
||||
? vars.master.heating.maxTemp
|
||||
: settings.heating.maxTemp;
|
||||
}
|
||||
@@ -137,7 +137,7 @@ protected:
|
||||
if (vars.emergency.state) {
|
||||
return settings.emergency.target;
|
||||
|
||||
} else if (settings.opentherm.nativeHeatingControl) {
|
||||
} else if (settings.opentherm.options.nativeHeatingControl) {
|
||||
return settings.heating.target;
|
||||
|
||||
} else if (!settings.equitherm.enabled && !settings.pid.enabled) {
|
||||
|
||||
@@ -175,16 +175,19 @@ protected:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (millis() - this->dallasSearchTime[gpio] > this->dallasSearchInterval) {
|
||||
this->dallasSearchTime[gpio] = millis();
|
||||
instance.begin();
|
||||
|
||||
Log.straceln(
|
||||
FPSTR(L_SENSORS_DALLAS),
|
||||
F("GPIO %hhu, devices on bus: %hhu, DS18* devices: %hhu"),
|
||||
gpio, instance.getDeviceCount(), instance.getDS18Count()
|
||||
);
|
||||
if (millis() - this->dallasSearchTime[gpio] < this->dallasSearchInterval) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this->dallasSearchTime[gpio] = millis();
|
||||
this->owInstances[gpio].reset();
|
||||
instance.begin();
|
||||
|
||||
Log.straceln(
|
||||
FPSTR(L_SENSORS_DALLAS),
|
||||
F("GPIO %hhu, devices on bus: %hhu, DS18* devices: %hhu"),
|
||||
gpio, instance.getDeviceCount(), instance.getDS18Count()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,25 +277,14 @@ protected:
|
||||
unsigned long ts = millis();
|
||||
|
||||
if (this->dallasPolling[gpio]) {
|
||||
auto minPollingTime = instance.millisToWaitForConversion(12);
|
||||
auto minPollingTime = instance.millisToWaitForConversion(12) * 2;
|
||||
unsigned long estimatePollingTime = ts - this->dallasLastPollingTime[gpio];
|
||||
|
||||
// check conversion time
|
||||
// isConversionComplete does not work with chinese clones!
|
||||
if (estimatePollingTime < minPollingTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check conversion
|
||||
bool conversionComplete = instance.isConversionComplete();
|
||||
if (!conversionComplete) {
|
||||
if (estimatePollingTime > (minPollingTime * 2)) {
|
||||
this->dallasPolling[gpio] = false;
|
||||
|
||||
Log.swarningln(FPSTR(L_SENSORS_DALLAS), F("GPIO %hhu, timeout receiving data"), gpio);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// read sensors data for current instance
|
||||
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
||||
@@ -345,28 +337,6 @@ protected:
|
||||
continue;
|
||||
}
|
||||
|
||||
// check sensors on bus
|
||||
if (!instance.getDeviceCount()) {
|
||||
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
||||
auto& sSensor = Sensors::settings[sensorId];
|
||||
|
||||
// only target & valid sensors
|
||||
if (!sSensor.enabled || sSensor.type != Sensors::Type::DALLAS_TEMP || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) {
|
||||
continue;
|
||||
|
||||
} else if (sSensor.gpio != gpio || isEmptyAddress(sSensor.address)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& rSensor = Sensors::results[sensorId];
|
||||
if (rSensor.signalQuality > 0) {
|
||||
rSensor.signalQuality--;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// start polling
|
||||
instance.setResolution(12);
|
||||
instance.requestTemperatures();
|
||||
@@ -380,10 +350,10 @@ protected:
|
||||
|
||||
void pollingBleSensors() {
|
||||
#if USE_BLE
|
||||
if (!NimBLEDevice::getInitialized() && millis() > 5000) {
|
||||
if (!NimBLEDevice::isInitialized() && millis() > 5000) {
|
||||
Log.sinfoln(FPSTR(L_SENSORS_BLE), F("Initialized"));
|
||||
BLEDevice::init("");
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
||||
NimBLEDevice::setPower(9);
|
||||
}
|
||||
|
||||
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
||||
@@ -445,7 +415,7 @@ protected:
|
||||
|
||||
bool connectToBleDevice(const uint8_t sensorId) {
|
||||
#if USE_BLE
|
||||
if (!NimBLEDevice::getInitialized()) {
|
||||
if (!NimBLEDevice::isInitialized()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -460,7 +430,7 @@ protected:
|
||||
sSensor.address[0], sSensor.address[1], sSensor.address[2],
|
||||
sSensor.address[3], sSensor.address[4], sSensor.address[5]
|
||||
};
|
||||
const NimBLEAddress address = NimBLEAddress(addr);
|
||||
const auto address = NimBLEAddress(addr, 0);
|
||||
|
||||
NimBLEClient* pClient = nullptr;
|
||||
pClient = NimBLEDevice::getClientByPeerAddress(address);
|
||||
@@ -470,12 +440,13 @@ protected:
|
||||
}
|
||||
|
||||
if (pClient == nullptr) {
|
||||
if (NimBLEDevice::getClientListSize() >= NIMBLE_MAX_CONNECTIONS) {
|
||||
if (NimBLEDevice::getCreatedClientCount() >= NIMBLE_MAX_CONNECTIONS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pClient = NimBLEDevice::createClient();
|
||||
pClient->setConnectTimeout(5);
|
||||
pClient->setConnectTimeout(5000);
|
||||
pClient->setSelfDelete(false, true);
|
||||
}
|
||||
|
||||
if(pClient->isConnected()) {
|
||||
@@ -492,7 +463,6 @@ protected:
|
||||
sensorId, sSensor.name, address.toString().c_str()
|
||||
);
|
||||
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -536,7 +506,7 @@ protected:
|
||||
return;
|
||||
}
|
||||
|
||||
NimBLERemoteService* pService = pChar->getRemoteService();
|
||||
const NimBLERemoteService* pService = pChar->getRemoteService();
|
||||
if (pService == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -609,7 +579,7 @@ protected:
|
||||
return;
|
||||
}
|
||||
|
||||
NimBLERemoteService* pService = pChar->getRemoteService();
|
||||
const NimBLERemoteService* pService = pChar->getRemoteService();
|
||||
if (pService == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -694,7 +664,7 @@ protected:
|
||||
return;
|
||||
}
|
||||
|
||||
NimBLERemoteService* pService = pChar->getRemoteService();
|
||||
const NimBLERemoteService* pService = pChar->getRemoteService();
|
||||
if (pService == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -793,7 +763,7 @@ protected:
|
||||
return;
|
||||
}
|
||||
|
||||
NimBLERemoteService* pService = pChar->getRemoteService();
|
||||
const NimBLERemoteService* pService = pChar->getRemoteService();
|
||||
if (pService == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -57,16 +57,21 @@ struct Settings {
|
||||
float minPower = 0.0f;
|
||||
float maxPower = 0.0f;
|
||||
|
||||
bool dhwPresent = true;
|
||||
bool summerWinterMode = false;
|
||||
bool heatingCh2Enabled = true;
|
||||
bool heatingCh1ToCh2 = false;
|
||||
bool dhwToCh2 = false;
|
||||
bool dhwBlocking = false;
|
||||
bool modulationSyncWithHeating = false;
|
||||
bool getMinMaxTemp = true;
|
||||
bool nativeHeatingControl = false;
|
||||
bool immergasFix = false;
|
||||
struct {
|
||||
bool dhwSupport = true;
|
||||
bool coolingSupport = false;
|
||||
bool summerWinterMode = false;
|
||||
bool heatingStateToSummerWinterMode = false;
|
||||
bool ch2AlwaysEnabled = true;
|
||||
bool heatingToCh2 = false;
|
||||
bool dhwToCh2 = false;
|
||||
bool dhwBlocking = false;
|
||||
bool modulationSyncWithHeating = false;
|
||||
bool maxTempSyncWithTargetTemp = true;
|
||||
bool getMinMaxTemp = true;
|
||||
bool nativeHeatingControl = false;
|
||||
bool immergasFix = false;
|
||||
} options;
|
||||
} opentherm;
|
||||
|
||||
struct {
|
||||
@@ -287,6 +292,7 @@ struct Variables {
|
||||
|
||||
bool connected = false;
|
||||
bool flame = false;
|
||||
bool cooling = false;
|
||||
float pressure = 0.0f;
|
||||
float heatExchangerTemp = 0.0f;
|
||||
|
||||
|
||||
379
src/strings.h
@@ -3,192 +3,197 @@
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
const char L_SETTINGS[] PROGMEM = "SETTINGS";
|
||||
const char L_SETTINGS_OT[] PROGMEM = "SETTINGS.OT";
|
||||
const char L_SETTINGS_DHW[] PROGMEM = "SETTINGS.DHW";
|
||||
const char L_SETTINGS_HEATING[] PROGMEM = "SETTINGS.HEATING";
|
||||
const char L_NETWORK[] PROGMEM = "NETWORK";
|
||||
const char L_NETWORK_SETTINGS[] PROGMEM = "NETWORK.SETTINGS";
|
||||
const char L_PORTAL_WEBSERVER[] PROGMEM = "PORTAL.WEBSERVER";
|
||||
const char L_PORTAL_DNSSERVER[] PROGMEM = "PORTAL.DNSSERVER";
|
||||
const char L_PORTAL_CAPTIVE[] PROGMEM = "PORTAL.CAPTIVE";
|
||||
const char L_PORTAL_OTA[] PROGMEM = "PORTAL.OTA";
|
||||
const char L_MAIN[] PROGMEM = "MAIN";
|
||||
const char L_MQTT[] PROGMEM = "MQTT";
|
||||
const char L_MQTT_HA[] PROGMEM = "MQTT.HA";
|
||||
const char L_MQTT_MSG[] PROGMEM = "MQTT.MSG";
|
||||
const char L_OT[] PROGMEM = "OT";
|
||||
const char L_OT_DHW[] PROGMEM = "OT.DHW";
|
||||
const char L_OT_HEATING[] PROGMEM = "OT.HEATING";
|
||||
const char L_OT_CH2[] PROGMEM = "OT.CH2";
|
||||
const char L_SENSORS[] PROGMEM = "SENSORS";
|
||||
const char L_SENSORS_SETTINGS[] PROGMEM = "SENSORS.SETTINGS";
|
||||
const char L_SENSORS_DALLAS[] PROGMEM = "SENSORS.DALLAS";
|
||||
const char L_SENSORS_NTC[] PROGMEM = "SENSORS.NTC";
|
||||
const char L_SENSORS_BLE[] PROGMEM = "SENSORS.BLE";
|
||||
const char L_REGULATOR[] PROGMEM = "REGULATOR";
|
||||
const char L_REGULATOR_PID[] PROGMEM = "REGULATOR.PID";
|
||||
const char L_REGULATOR_EQUITHERM[] PROGMEM = "REGULATOR.EQUITHERM";
|
||||
const char L_CASCADE_INPUT[] PROGMEM = "CASCADE.INPUT";
|
||||
const char L_CASCADE_OUTPUT[] PROGMEM = "CASCADE.OUTPUT";
|
||||
const char L_EXTPUMP[] PROGMEM = "EXTPUMP";
|
||||
const char L_SETTINGS[] PROGMEM = "SETTINGS";
|
||||
const char L_SETTINGS_OT[] PROGMEM = "SETTINGS.OT";
|
||||
const char L_SETTINGS_DHW[] PROGMEM = "SETTINGS.DHW";
|
||||
const char L_SETTINGS_HEATING[] PROGMEM = "SETTINGS.HEATING";
|
||||
const char L_NETWORK[] PROGMEM = "NETWORK";
|
||||
const char L_NETWORK_SETTINGS[] PROGMEM = "NETWORK.SETTINGS";
|
||||
const char L_PORTAL_WEBSERVER[] PROGMEM = "PORTAL.WEBSERVER";
|
||||
const char L_PORTAL_DNSSERVER[] PROGMEM = "PORTAL.DNSSERVER";
|
||||
const char L_PORTAL_CAPTIVE[] PROGMEM = "PORTAL.CAPTIVE";
|
||||
const char L_PORTAL_OTA[] PROGMEM = "PORTAL.OTA";
|
||||
const char L_MAIN[] PROGMEM = "MAIN";
|
||||
const char L_MQTT[] PROGMEM = "MQTT";
|
||||
const char L_MQTT_HA[] PROGMEM = "MQTT.HA";
|
||||
const char L_MQTT_MSG[] PROGMEM = "MQTT.MSG";
|
||||
const char L_OT[] PROGMEM = "OT";
|
||||
const char L_OT_DHW[] PROGMEM = "OT.DHW";
|
||||
const char L_OT_HEATING[] PROGMEM = "OT.HEATING";
|
||||
const char L_OT_CH2[] PROGMEM = "OT.CH2";
|
||||
const char L_SENSORS[] PROGMEM = "SENSORS";
|
||||
const char L_SENSORS_SETTINGS[] PROGMEM = "SENSORS.SETTINGS";
|
||||
const char L_SENSORS_DALLAS[] PROGMEM = "SENSORS.DALLAS";
|
||||
const char L_SENSORS_NTC[] PROGMEM = "SENSORS.NTC";
|
||||
const char L_SENSORS_BLE[] PROGMEM = "SENSORS.BLE";
|
||||
const char L_REGULATOR[] PROGMEM = "REGULATOR";
|
||||
const char L_REGULATOR_PID[] PROGMEM = "REGULATOR.PID";
|
||||
const char L_REGULATOR_EQUITHERM[] PROGMEM = "REGULATOR.EQUITHERM";
|
||||
const char L_CASCADE_INPUT[] PROGMEM = "CASCADE.INPUT";
|
||||
const char L_CASCADE_OUTPUT[] PROGMEM = "CASCADE.OUTPUT";
|
||||
const char L_EXTPUMP[] PROGMEM = "EXTPUMP";
|
||||
|
||||
|
||||
const char S_ACTIONS[] PROGMEM = "actions";
|
||||
const char S_ACTIVE[] PROGMEM = "active";
|
||||
const char S_ADDRESS[] PROGMEM = "address";
|
||||
const char S_ANTI_STUCK_INTERVAL[] PROGMEM = "antiStuckInterval";
|
||||
const char S_ANTI_STUCK_TIME[] PROGMEM = "antiStuckTime";
|
||||
const char S_AP[] PROGMEM = "ap";
|
||||
const char S_APP_VERSION[] PROGMEM = "appVersion";
|
||||
const char S_AUTH[] PROGMEM = "auth";
|
||||
const char S_BACKTRACE[] PROGMEM = "backtrace";
|
||||
const char S_BATTERY[] PROGMEM = "battery";
|
||||
const char S_BAUDRATE[] PROGMEM = "baudrate";
|
||||
const char S_BLOCKING[] PROGMEM = "blocking";
|
||||
const char S_BSSID[] PROGMEM = "bssid";
|
||||
const char S_BUILD[] PROGMEM = "build";
|
||||
const char S_CASCADE_CONTROL[] PROGMEM = "cascadeControl";
|
||||
const char S_CHANNEL[] PROGMEM = "channel";
|
||||
const char S_CHIP[] PROGMEM = "chip";
|
||||
const char S_CODE[] PROGMEM = "code";
|
||||
const char S_CONNECTED[] PROGMEM = "connected";
|
||||
const char S_CONTINUES[] PROGMEM = "continues";
|
||||
const char S_CORE[] PROGMEM = "core";
|
||||
const char S_CORES[] PROGMEM = "cores";
|
||||
const char S_CRASH[] PROGMEM = "crash";
|
||||
const char S_CURRENT_TEMP[] PROGMEM = "currentTemp";
|
||||
const char S_DATA[] PROGMEM = "data";
|
||||
const char S_DATE[] PROGMEM = "date";
|
||||
const char S_DHW[] PROGMEM = "dhw";
|
||||
const char S_DHW_BLOCKING[] PROGMEM = "dhwBlocking";
|
||||
const char S_DHW_PRESENT[] PROGMEM = "dhwPresent";
|
||||
const char S_DHW_TO_CH2[] PROGMEM = "dhwToCh2";
|
||||
const char S_DIAG[] PROGMEM = "diag";
|
||||
const char S_DNS[] PROGMEM = "dns";
|
||||
const char S_DT[] PROGMEM = "dt";
|
||||
const char S_D_FACTOR[] PROGMEM = "d_factor";
|
||||
const char S_EMERGENCY[] PROGMEM = "emergency";
|
||||
const char S_ENABLED[] PROGMEM = "enabled";
|
||||
const char S_ENV[] PROGMEM = "env";
|
||||
const char S_EPC[] PROGMEM = "epc";
|
||||
const char S_EQUITHERM[] PROGMEM = "equitherm";
|
||||
const char S_EXTERNAL_PUMP[] PROGMEM = "externalPump";
|
||||
const char S_FACTOR[] PROGMEM = "factor";
|
||||
const char S_FAULT[] PROGMEM = "fault";
|
||||
const char S_FILTERING[] PROGMEM = "filtering";
|
||||
const char S_FILTERING_FACTOR[] PROGMEM = "filteringFactor";
|
||||
const char S_FLAGS[] PROGMEM = "flags";
|
||||
const char S_FLAME[] PROGMEM = "flame";
|
||||
const char S_FLASH[] PROGMEM = "flash";
|
||||
const char S_FREE[] PROGMEM = "free";
|
||||
const char S_FREQ[] PROGMEM = "freq";
|
||||
const char S_GATEWAY[] PROGMEM = "gateway";
|
||||
const char S_GET_MIN_MAX_TEMP[] PROGMEM = "getMinMaxTemp";
|
||||
const char S_GPIO[] PROGMEM = "gpio";
|
||||
const char S_HEAP[] PROGMEM = "heap";
|
||||
const char S_HEATING[] PROGMEM = "heating";
|
||||
const char S_HEATING_CH1_TO_CH2[] PROGMEM = "heatingCh1ToCh2";
|
||||
const char S_HEATING_CH2_ENABLED[] PROGMEM = "heatingCh2Enabled";
|
||||
const char S_HIDDEN[] PROGMEM = "hidden";
|
||||
const char S_HOME_ASSISTANT_DISCOVERY[] PROGMEM = "homeAssistantDiscovery";
|
||||
const char S_HOSTNAME[] PROGMEM = "hostname";
|
||||
const char S_HUMIDITY[] PROGMEM = "humidity";
|
||||
const char S_HYSTERESIS[] PROGMEM = "hysteresis";
|
||||
const char S_ID[] PROGMEM = "id";
|
||||
const char S_IMMERGAS_FIX[] PROGMEM = "immergasFix";
|
||||
const char S_INDOOR_TEMP[] PROGMEM = "indoorTemp";
|
||||
const char S_INDOOR_TEMP_CONTROL[] PROGMEM = "indoorTempControl";
|
||||
const char S_IN_GPIO[] PROGMEM = "inGpio";
|
||||
const char S_INPUT[] PROGMEM = "input";
|
||||
const char S_INTERVAL[] PROGMEM = "interval";
|
||||
const char S_INVERT_STATE[] PROGMEM = "invertState";
|
||||
const char S_IP[] PROGMEM = "ip";
|
||||
const char S_I_FACTOR[] PROGMEM = "i_factor";
|
||||
const char S_K_FACTOR[] PROGMEM = "k_factor";
|
||||
const char S_LOGIN[] PROGMEM = "login";
|
||||
const char S_LOG_LEVEL[] PROGMEM = "logLevel";
|
||||
const char S_MAC[] PROGMEM = "mac";
|
||||
const char S_MASTER[] PROGMEM = "master";
|
||||
const char S_MAX[] PROGMEM = "max";
|
||||
const char S_MAX_FREE_BLOCK[] PROGMEM = "maxFreeBlock";
|
||||
const char S_MAX_MODULATION[] PROGMEM = "maxModulation";
|
||||
const char S_MAX_POWER[] PROGMEM = "maxPower";
|
||||
const char S_MAX_TEMP[] PROGMEM = "maxTemp";
|
||||
const char S_MEMBER_ID[] PROGMEM = "memberId";
|
||||
const char S_MIN[] PROGMEM = "min";
|
||||
const char S_MIN_FREE[] PROGMEM = "minFree";
|
||||
const char S_MIN_MAX_FREE_BLOCK[] PROGMEM = "minMaxFreeBlock";
|
||||
const char S_MIN_POWER[] PROGMEM = "minPower";
|
||||
const char S_MIN_TEMP[] PROGMEM = "minTemp";
|
||||
const char S_MODEL[] PROGMEM = "model";
|
||||
const char S_MODULATION[] PROGMEM = "modulation";
|
||||
const char S_MODULATION_SYNC_WITH_HEATING[] PROGMEM = "modulationSyncWithHeating";
|
||||
const char S_MQTT[] PROGMEM = "mqtt";
|
||||
const char S_NAME[] PROGMEM = "name";
|
||||
const char S_NATIVE_HEATING_CONTROL[] PROGMEM = "nativeHeatingControl";
|
||||
const char S_NETWORK[] PROGMEM = "network";
|
||||
const char S_N_FACTOR[] PROGMEM = "n_factor";
|
||||
const char S_OFFSET[] PROGMEM = "offset";
|
||||
const char S_ON_ENABLED_HEATING[] PROGMEM = "onEnabledHeating";
|
||||
const char S_ON_FAULT[] PROGMEM = "onFault";
|
||||
const char S_ON_LOSS_CONNECTION[] PROGMEM = "onLossConnection";
|
||||
const char S_OPENTHERM[] PROGMEM = "opentherm";
|
||||
const char S_OUTDOOR_TEMP[] PROGMEM = "outdoorTemp";
|
||||
const char S_OUT_GPIO[] PROGMEM = "outGpio";
|
||||
const char S_OUTPUT[] PROGMEM = "output";
|
||||
const char S_PASSWORD[] PROGMEM = "password";
|
||||
const char S_PID[] PROGMEM = "pid";
|
||||
const char S_PORT[] PROGMEM = "port";
|
||||
const char S_PORTAL[] PROGMEM = "portal";
|
||||
const char S_POST_CIRCULATION_TIME[] PROGMEM = "postCirculationTime";
|
||||
const char S_POWER[] PROGMEM = "power";
|
||||
const char S_PREFIX[] PROGMEM = "prefix";
|
||||
const char S_PROTOCOL_VERSION[] PROGMEM = "protocolVersion";
|
||||
const char S_PURPOSE[] PROGMEM = "purpose";
|
||||
const char S_P_FACTOR[] PROGMEM = "p_factor";
|
||||
const char S_REAL_SIZE[] PROGMEM = "realSize";
|
||||
const char S_REASON[] PROGMEM = "reason";
|
||||
const char S_RESET_DIAGNOSTIC[] PROGMEM = "resetDiagnostic";
|
||||
const char S_RESET_FAULT[] PROGMEM = "resetFault";
|
||||
const char S_RESET_REASON[] PROGMEM = "resetReason";
|
||||
const char S_RESTART[] PROGMEM = "restart";
|
||||
const char S_RETURN_TEMP[] PROGMEM = "returnTemp";
|
||||
const char S_REV[] PROGMEM = "rev";
|
||||
const char S_RSSI[] PROGMEM = "rssi";
|
||||
const char S_RX_LED_GPIO[] PROGMEM = "rxLedGpio";
|
||||
const char S_SDK[] PROGMEM = "sdk";
|
||||
const char S_SENSORS[] PROGMEM = "sensors";
|
||||
const char S_SERIAL[] PROGMEM = "serial";
|
||||
const char S_SERVER[] PROGMEM = "server";
|
||||
const char S_SETTINGS[] PROGMEM = "settings";
|
||||
const char S_SIGNAL_QUALITY[] PROGMEM = "signalQuality";
|
||||
const char S_SIZE[] PROGMEM = "size";
|
||||
const char S_SLAVE[] PROGMEM = "slave";
|
||||
const char S_SSID[] PROGMEM = "ssid";
|
||||
const char S_STA[] PROGMEM = "sta";
|
||||
const char S_STATE[] PROGMEM = "state";
|
||||
const char S_STATIC_CONFIG[] PROGMEM = "staticConfig";
|
||||
const char S_STATUS_LED_GPIO[] PROGMEM = "statusLedGpio";
|
||||
const char S_SETPOINT_TEMP[] PROGMEM = "setpointTemp";
|
||||
const char S_SUBNET[] PROGMEM = "subnet";
|
||||
const char S_SUMMER_WINTER_MODE[] PROGMEM = "summerWinterMode";
|
||||
const char S_SYSTEM[] PROGMEM = "system";
|
||||
const char S_TARGET[] PROGMEM = "target";
|
||||
const char S_TARGET_TEMP[] PROGMEM = "targetTemp";
|
||||
const char S_TELNET[] PROGMEM = "telnet";
|
||||
const char S_TEMPERATURE[] PROGMEM = "temperature";
|
||||
const char S_THRESHOLD_TIME[] PROGMEM = "thresholdTime";
|
||||
const char S_TOTAL[] PROGMEM = "total";
|
||||
const char S_TRESHOLD_TIME[] PROGMEM = "tresholdTime";
|
||||
const char S_TURBO[] PROGMEM = "turbo";
|
||||
const char S_TURBO_FACTOR[] PROGMEM = "turboFactor";
|
||||
const char S_TYPE[] PROGMEM = "type";
|
||||
const char S_T_FACTOR[] PROGMEM = "t_factor";
|
||||
const char S_UNIT_SYSTEM[] PROGMEM = "unitSystem";
|
||||
const char S_UPTIME[] PROGMEM = "uptime";
|
||||
const char S_USE[] PROGMEM = "use";
|
||||
const char S_USE_DHCP[] PROGMEM = "useDhcp";
|
||||
const char S_USER[] PROGMEM = "user";
|
||||
const char S_VALUE[] PROGMEM = "value";
|
||||
const char S_VERSION[] PROGMEM = "version";
|
||||
const char S_ACTIONS[] PROGMEM = "actions";
|
||||
const char S_ACTIVE[] PROGMEM = "active";
|
||||
const char S_ADDRESS[] PROGMEM = "address";
|
||||
const char S_ANTI_STUCK_INTERVAL[] PROGMEM = "antiStuckInterval";
|
||||
const char S_ANTI_STUCK_TIME[] PROGMEM = "antiStuckTime";
|
||||
const char S_AP[] PROGMEM = "ap";
|
||||
const char S_APP_VERSION[] PROGMEM = "appVersion";
|
||||
const char S_AUTH[] PROGMEM = "auth";
|
||||
const char S_BACKTRACE[] PROGMEM = "backtrace";
|
||||
const char S_BATTERY[] PROGMEM = "battery";
|
||||
const char S_BAUDRATE[] PROGMEM = "baudrate";
|
||||
const char S_BLOCKING[] PROGMEM = "blocking";
|
||||
const char S_BSSID[] PROGMEM = "bssid";
|
||||
const char S_BUILD[] PROGMEM = "build";
|
||||
const char S_CASCADE_CONTROL[] PROGMEM = "cascadeControl";
|
||||
const char S_CHANNEL[] PROGMEM = "channel";
|
||||
const char S_CH2_ALWAYS_ENABLED[] PROGMEM = "ch2AlwaysEnabled";
|
||||
const char S_CHIP[] PROGMEM = "chip";
|
||||
const char S_CODE[] PROGMEM = "code";
|
||||
const char S_CONNECTED[] PROGMEM = "connected";
|
||||
const char S_CONTINUES[] PROGMEM = "continues";
|
||||
const char S_COOLING[] PROGMEM = "cooling";
|
||||
const char S_COOLING_SUPPORT[] PROGMEM = "coolingSupport";
|
||||
const char S_CORE[] PROGMEM = "core";
|
||||
const char S_CORES[] PROGMEM = "cores";
|
||||
const char S_CRASH[] PROGMEM = "crash";
|
||||
const char S_CURRENT_TEMP[] PROGMEM = "currentTemp";
|
||||
const char S_DATA[] PROGMEM = "data";
|
||||
const char S_DATE[] PROGMEM = "date";
|
||||
const char S_DHW[] PROGMEM = "dhw";
|
||||
const char S_DHW_BLOCKING[] PROGMEM = "dhwBlocking";
|
||||
const char S_DHW_SUPPORT[] PROGMEM = "dhwSupport";
|
||||
const char S_DHW_TO_CH2[] PROGMEM = "dhwToCh2";
|
||||
const char S_DIAG[] PROGMEM = "diag";
|
||||
const char S_DNS[] PROGMEM = "dns";
|
||||
const char S_DT[] PROGMEM = "dt";
|
||||
const char S_D_FACTOR[] PROGMEM = "d_factor";
|
||||
const char S_EMERGENCY[] PROGMEM = "emergency";
|
||||
const char S_ENABLED[] PROGMEM = "enabled";
|
||||
const char S_ENV[] PROGMEM = "env";
|
||||
const char S_EPC[] PROGMEM = "epc";
|
||||
const char S_EQUITHERM[] PROGMEM = "equitherm";
|
||||
const char S_EXTERNAL_PUMP[] PROGMEM = "externalPump";
|
||||
const char S_FACTOR[] PROGMEM = "factor";
|
||||
const char S_FAULT[] PROGMEM = "fault";
|
||||
const char S_FILTERING[] PROGMEM = "filtering";
|
||||
const char S_FILTERING_FACTOR[] PROGMEM = "filteringFactor";
|
||||
const char S_FLAGS[] PROGMEM = "flags";
|
||||
const char S_FLAME[] PROGMEM = "flame";
|
||||
const char S_FLASH[] PROGMEM = "flash";
|
||||
const char S_FREE[] PROGMEM = "free";
|
||||
const char S_FREQ[] PROGMEM = "freq";
|
||||
const char S_GATEWAY[] PROGMEM = "gateway";
|
||||
const char S_GET_MIN_MAX_TEMP[] PROGMEM = "getMinMaxTemp";
|
||||
const char S_GPIO[] PROGMEM = "gpio";
|
||||
const char S_HEAP[] PROGMEM = "heap";
|
||||
const char S_HEATING[] PROGMEM = "heating";
|
||||
const char S_HEATING_TO_CH2[] PROGMEM = "heatingToCh2";
|
||||
const char S_HEATING_STATE_TO_SUMMER_WINTER_MODE[] PROGMEM = "heatingStateToSummerWinterMode";
|
||||
const char S_HIDDEN[] PROGMEM = "hidden";
|
||||
const char S_HOME_ASSISTANT_DISCOVERY[] PROGMEM = "homeAssistantDiscovery";
|
||||
const char S_HOSTNAME[] PROGMEM = "hostname";
|
||||
const char S_HUMIDITY[] PROGMEM = "humidity";
|
||||
const char S_HYSTERESIS[] PROGMEM = "hysteresis";
|
||||
const char S_ID[] PROGMEM = "id";
|
||||
const char S_IMMERGAS_FIX[] PROGMEM = "immergasFix";
|
||||
const char S_INDOOR_TEMP[] PROGMEM = "indoorTemp";
|
||||
const char S_INDOOR_TEMP_CONTROL[] PROGMEM = "indoorTempControl";
|
||||
const char S_IN_GPIO[] PROGMEM = "inGpio";
|
||||
const char S_INPUT[] PROGMEM = "input";
|
||||
const char S_INTERVAL[] PROGMEM = "interval";
|
||||
const char S_INVERT_STATE[] PROGMEM = "invertState";
|
||||
const char S_IP[] PROGMEM = "ip";
|
||||
const char S_I_FACTOR[] PROGMEM = "i_factor";
|
||||
const char S_K_FACTOR[] PROGMEM = "k_factor";
|
||||
const char S_LOGIN[] PROGMEM = "login";
|
||||
const char S_LOG_LEVEL[] PROGMEM = "logLevel";
|
||||
const char S_MAC[] PROGMEM = "mac";
|
||||
const char S_MASTER[] PROGMEM = "master";
|
||||
const char S_MAX[] PROGMEM = "max";
|
||||
const char S_MAX_FREE_BLOCK[] PROGMEM = "maxFreeBlock";
|
||||
const char S_MAX_MODULATION[] PROGMEM = "maxModulation";
|
||||
const char S_MAX_POWER[] PROGMEM = "maxPower";
|
||||
const char S_MAX_TEMP[] PROGMEM = "maxTemp";
|
||||
const char S_MAX_TEMP_SYNC_WITH_TARGET_TEMP[] PROGMEM = "maxTempSyncWithTargetTemp";
|
||||
const char S_MEMBER_ID[] PROGMEM = "memberId";
|
||||
const char S_MIN[] PROGMEM = "min";
|
||||
const char S_MIN_FREE[] PROGMEM = "minFree";
|
||||
const char S_MIN_MAX_FREE_BLOCK[] PROGMEM = "minMaxFreeBlock";
|
||||
const char S_MIN_POWER[] PROGMEM = "minPower";
|
||||
const char S_MIN_TEMP[] PROGMEM = "minTemp";
|
||||
const char S_MODEL[] PROGMEM = "model";
|
||||
const char S_MODULATION[] PROGMEM = "modulation";
|
||||
const char S_MODULATION_SYNC_WITH_HEATING[] PROGMEM = "modulationSyncWithHeating";
|
||||
const char S_MQTT[] PROGMEM = "mqtt";
|
||||
const char S_NAME[] PROGMEM = "name";
|
||||
const char S_NATIVE_HEATING_CONTROL[] PROGMEM = "nativeHeatingControl";
|
||||
const char S_NETWORK[] PROGMEM = "network";
|
||||
const char S_N_FACTOR[] PROGMEM = "n_factor";
|
||||
const char S_OFFSET[] PROGMEM = "offset";
|
||||
const char S_ON_ENABLED_HEATING[] PROGMEM = "onEnabledHeating";
|
||||
const char S_ON_FAULT[] PROGMEM = "onFault";
|
||||
const char S_ON_LOSS_CONNECTION[] PROGMEM = "onLossConnection";
|
||||
const char S_OPENTHERM[] PROGMEM = "opentherm";
|
||||
const char S_OPTIONS[] PROGMEM = "options";
|
||||
const char S_OUTDOOR_TEMP[] PROGMEM = "outdoorTemp";
|
||||
const char S_OUT_GPIO[] PROGMEM = "outGpio";
|
||||
const char S_OUTPUT[] PROGMEM = "output";
|
||||
const char S_PASSWORD[] PROGMEM = "password";
|
||||
const char S_PID[] PROGMEM = "pid";
|
||||
const char S_PORT[] PROGMEM = "port";
|
||||
const char S_PORTAL[] PROGMEM = "portal";
|
||||
const char S_POST_CIRCULATION_TIME[] PROGMEM = "postCirculationTime";
|
||||
const char S_POWER[] PROGMEM = "power";
|
||||
const char S_PREFIX[] PROGMEM = "prefix";
|
||||
const char S_PROTOCOL_VERSION[] PROGMEM = "protocolVersion";
|
||||
const char S_PURPOSE[] PROGMEM = "purpose";
|
||||
const char S_P_FACTOR[] PROGMEM = "p_factor";
|
||||
const char S_REAL_SIZE[] PROGMEM = "realSize";
|
||||
const char S_REASON[] PROGMEM = "reason";
|
||||
const char S_RESET_DIAGNOSTIC[] PROGMEM = "resetDiagnostic";
|
||||
const char S_RESET_FAULT[] PROGMEM = "resetFault";
|
||||
const char S_RESET_REASON[] PROGMEM = "resetReason";
|
||||
const char S_RESTART[] PROGMEM = "restart";
|
||||
const char S_RETURN_TEMP[] PROGMEM = "returnTemp";
|
||||
const char S_REV[] PROGMEM = "rev";
|
||||
const char S_RSSI[] PROGMEM = "rssi";
|
||||
const char S_RX_LED_GPIO[] PROGMEM = "rxLedGpio";
|
||||
const char S_SDK[] PROGMEM = "sdk";
|
||||
const char S_SENSORS[] PROGMEM = "sensors";
|
||||
const char S_SERIAL[] PROGMEM = "serial";
|
||||
const char S_SERVER[] PROGMEM = "server";
|
||||
const char S_SETTINGS[] PROGMEM = "settings";
|
||||
const char S_SIGNAL_QUALITY[] PROGMEM = "signalQuality";
|
||||
const char S_SIZE[] PROGMEM = "size";
|
||||
const char S_SLAVE[] PROGMEM = "slave";
|
||||
const char S_SSID[] PROGMEM = "ssid";
|
||||
const char S_STA[] PROGMEM = "sta";
|
||||
const char S_STATE[] PROGMEM = "state";
|
||||
const char S_STATIC_CONFIG[] PROGMEM = "staticConfig";
|
||||
const char S_STATUS_LED_GPIO[] PROGMEM = "statusLedGpio";
|
||||
const char S_SETPOINT_TEMP[] PROGMEM = "setpointTemp";
|
||||
const char S_SUBNET[] PROGMEM = "subnet";
|
||||
const char S_SUMMER_WINTER_MODE[] PROGMEM = "summerWinterMode";
|
||||
const char S_SYSTEM[] PROGMEM = "system";
|
||||
const char S_TARGET[] PROGMEM = "target";
|
||||
const char S_TARGET_TEMP[] PROGMEM = "targetTemp";
|
||||
const char S_TELNET[] PROGMEM = "telnet";
|
||||
const char S_TEMPERATURE[] PROGMEM = "temperature";
|
||||
const char S_THRESHOLD_TIME[] PROGMEM = "thresholdTime";
|
||||
const char S_TOTAL[] PROGMEM = "total";
|
||||
const char S_TRESHOLD_TIME[] PROGMEM = "tresholdTime";
|
||||
const char S_TURBO[] PROGMEM = "turbo";
|
||||
const char S_TURBO_FACTOR[] PROGMEM = "turboFactor";
|
||||
const char S_TYPE[] PROGMEM = "type";
|
||||
const char S_T_FACTOR[] PROGMEM = "t_factor";
|
||||
const char S_UNIT_SYSTEM[] PROGMEM = "unitSystem";
|
||||
const char S_UPTIME[] PROGMEM = "uptime";
|
||||
const char S_USE[] PROGMEM = "use";
|
||||
const char S_USE_DHCP[] PROGMEM = "useDhcp";
|
||||
const char S_USER[] PROGMEM = "user";
|
||||
const char S_VALUE[] PROGMEM = "value";
|
||||
const char S_VERSION[] PROGMEM = "version";
|
||||
|
||||
159
src/utils.h
@@ -377,16 +377,21 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
|
||||
opentherm[FPSTR(S_MAX_MODULATION)] = src.opentherm.maxModulation;
|
||||
opentherm[FPSTR(S_MIN_POWER)] = roundf(src.opentherm.minPower, 2);
|
||||
opentherm[FPSTR(S_MAX_POWER)] = roundf(src.opentherm.maxPower, 2);
|
||||
opentherm[FPSTR(S_DHW_PRESENT)] = src.opentherm.dhwPresent;
|
||||
opentherm[FPSTR(S_SUMMER_WINTER_MODE)] = src.opentherm.summerWinterMode;
|
||||
opentherm[FPSTR(S_HEATING_CH2_ENABLED)] = src.opentherm.heatingCh2Enabled;
|
||||
opentherm[FPSTR(S_HEATING_CH1_TO_CH2)] = src.opentherm.heatingCh1ToCh2;
|
||||
opentherm[FPSTR(S_DHW_TO_CH2)] = src.opentherm.dhwToCh2;
|
||||
opentherm[FPSTR(S_DHW_BLOCKING)] = src.opentherm.dhwBlocking;
|
||||
opentherm[FPSTR(S_MODULATION_SYNC_WITH_HEATING)] = src.opentherm.modulationSyncWithHeating;
|
||||
opentherm[FPSTR(S_GET_MIN_MAX_TEMP)] = src.opentherm.getMinMaxTemp;
|
||||
opentherm[FPSTR(S_NATIVE_HEATING_CONTROL)] = src.opentherm.nativeHeatingControl;
|
||||
opentherm[FPSTR(S_IMMERGAS_FIX)] = src.opentherm.immergasFix;
|
||||
|
||||
auto otOptions = opentherm[FPSTR(S_OPTIONS)].to<JsonObject>();
|
||||
otOptions[FPSTR(S_DHW_SUPPORT)] = src.opentherm.options.dhwSupport;
|
||||
otOptions[FPSTR(S_COOLING_SUPPORT)] = src.opentherm.options.coolingSupport;
|
||||
otOptions[FPSTR(S_SUMMER_WINTER_MODE)] = src.opentherm.options.summerWinterMode;
|
||||
otOptions[FPSTR(S_HEATING_STATE_TO_SUMMER_WINTER_MODE)] = src.opentherm.options.heatingStateToSummerWinterMode;
|
||||
otOptions[FPSTR(S_CH2_ALWAYS_ENABLED)] = src.opentherm.options.ch2AlwaysEnabled;
|
||||
otOptions[FPSTR(S_HEATING_TO_CH2)] = src.opentherm.options.heatingToCh2;
|
||||
otOptions[FPSTR(S_DHW_TO_CH2)] = src.opentherm.options.dhwToCh2;
|
||||
otOptions[FPSTR(S_DHW_BLOCKING)] = src.opentherm.options.dhwBlocking;
|
||||
otOptions[FPSTR(S_MODULATION_SYNC_WITH_HEATING)] = src.opentherm.options.modulationSyncWithHeating;
|
||||
otOptions[FPSTR(S_MAX_TEMP_SYNC_WITH_TARGET_TEMP)] = src.opentherm.options.maxTempSyncWithTargetTemp;
|
||||
otOptions[FPSTR(S_GET_MIN_MAX_TEMP)] = src.opentherm.options.getMinMaxTemp;
|
||||
otOptions[FPSTR(S_NATIVE_HEATING_CONTROL)] = src.opentherm.options.nativeHeatingControl;
|
||||
otOptions[FPSTR(S_IMMERGAS_FIX)] = src.opentherm.options.immergasFix;
|
||||
|
||||
auto mqtt = dst[FPSTR(S_MQTT)].to<JsonObject>();
|
||||
mqtt[FPSTR(S_ENABLED)] = src.mqtt.enabled;
|
||||
@@ -718,101 +723,128 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_PRESENT)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_PRESENT)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_SUPPORT)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_SUPPORT)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.dhwPresent) {
|
||||
dst.opentherm.dhwPresent = value;
|
||||
if (value != dst.opentherm.options.dhwSupport) {
|
||||
dst.opentherm.options.dhwSupport = value;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_SUMMER_WINTER_MODE)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_SUMMER_WINTER_MODE)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_COOLING_SUPPORT)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_COOLING_SUPPORT)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.summerWinterMode) {
|
||||
dst.opentherm.summerWinterMode = value;
|
||||
if (value != dst.opentherm.options.coolingSupport) {
|
||||
dst.opentherm.options.coolingSupport = value;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_HEATING_CH2_ENABLED)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_HEATING_CH2_ENABLED)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_SUMMER_WINTER_MODE)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_SUMMER_WINTER_MODE)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.heatingCh2Enabled) {
|
||||
dst.opentherm.heatingCh2Enabled = value;
|
||||
if (value != dst.opentherm.options.summerWinterMode) {
|
||||
dst.opentherm.options.summerWinterMode = value;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dst.opentherm.heatingCh2Enabled) {
|
||||
dst.opentherm.heatingCh1ToCh2 = false;
|
||||
dst.opentherm.dhwToCh2 = false;
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_HEATING_STATE_TO_SUMMER_WINTER_MODE)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_HEATING_STATE_TO_SUMMER_WINTER_MODE)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.options.heatingStateToSummerWinterMode) {
|
||||
dst.opentherm.options.heatingStateToSummerWinterMode = value;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_CH2_ALWAYS_ENABLED)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_CH2_ALWAYS_ENABLED)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.options.ch2AlwaysEnabled) {
|
||||
dst.opentherm.options.ch2AlwaysEnabled = value;
|
||||
|
||||
if (dst.opentherm.options.ch2AlwaysEnabled) {
|
||||
dst.opentherm.options.heatingToCh2 = false;
|
||||
dst.opentherm.options.dhwToCh2 = false;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_HEATING_CH1_TO_CH2)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_HEATING_CH1_TO_CH2)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_HEATING_TO_CH2)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_HEATING_TO_CH2)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.heatingCh1ToCh2) {
|
||||
dst.opentherm.heatingCh1ToCh2 = value;
|
||||
if (value != dst.opentherm.options.heatingToCh2) {
|
||||
dst.opentherm.options.heatingToCh2 = value;
|
||||
|
||||
if (dst.opentherm.heatingCh1ToCh2) {
|
||||
dst.opentherm.heatingCh2Enabled = false;
|
||||
dst.opentherm.dhwToCh2 = false;
|
||||
if (dst.opentherm.options.heatingToCh2) {
|
||||
dst.opentherm.options.ch2AlwaysEnabled = false;
|
||||
dst.opentherm.options.dhwToCh2 = false;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_TO_CH2)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_TO_CH2)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_TO_CH2)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_TO_CH2)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.dhwToCh2) {
|
||||
dst.opentherm.dhwToCh2 = value;
|
||||
if (value != dst.opentherm.options.dhwToCh2) {
|
||||
dst.opentherm.options.dhwToCh2 = value;
|
||||
|
||||
if (dst.opentherm.dhwToCh2) {
|
||||
dst.opentherm.heatingCh2Enabled = false;
|
||||
dst.opentherm.heatingCh1ToCh2 = false;
|
||||
if (dst.opentherm.options.dhwToCh2) {
|
||||
dst.opentherm.options.ch2AlwaysEnabled = false;
|
||||
dst.opentherm.options.heatingToCh2 = false;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_BLOCKING)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_BLOCKING)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_BLOCKING)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_BLOCKING)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.dhwBlocking) {
|
||||
dst.opentherm.dhwBlocking = value;
|
||||
if (value != dst.opentherm.options.dhwBlocking) {
|
||||
dst.opentherm.options.dhwBlocking = value;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_MODULATION_SYNC_WITH_HEATING)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_MODULATION_SYNC_WITH_HEATING)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MODULATION_SYNC_WITH_HEATING)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MODULATION_SYNC_WITH_HEATING)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.modulationSyncWithHeating) {
|
||||
dst.opentherm.modulationSyncWithHeating = value;
|
||||
if (value != dst.opentherm.options.modulationSyncWithHeating) {
|
||||
dst.opentherm.options.modulationSyncWithHeating = value;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_GET_MIN_MAX_TEMP)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_GET_MIN_MAX_TEMP)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MAX_TEMP_SYNC_WITH_TARGET_TEMP)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MAX_TEMP_SYNC_WITH_TARGET_TEMP)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.getMinMaxTemp) {
|
||||
dst.opentherm.getMinMaxTemp = value;
|
||||
if (value != dst.opentherm.options.maxTempSyncWithTargetTemp) {
|
||||
dst.opentherm.options.maxTempSyncWithTargetTemp = value;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_NATIVE_HEATING_CONTROL)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_NATIVE_HEATING_CONTROL)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_GET_MIN_MAX_TEMP)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_GET_MIN_MAX_TEMP)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.nativeHeatingControl) {
|
||||
dst.opentherm.nativeHeatingControl = value;
|
||||
if (value != dst.opentherm.options.getMinMaxTemp) {
|
||||
dst.opentherm.options.getMinMaxTemp = value;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_NATIVE_HEATING_CONTROL)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_NATIVE_HEATING_CONTROL)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.options.nativeHeatingControl) {
|
||||
dst.opentherm.options.nativeHeatingControl = value;
|
||||
|
||||
if (value) {
|
||||
dst.equitherm.enabled = false;
|
||||
@@ -823,11 +855,11 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
||||
}
|
||||
}
|
||||
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_IMMERGAS_FIX)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_IMMERGAS_FIX)].as<bool>();
|
||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_IMMERGAS_FIX)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_IMMERGAS_FIX)].as<bool>();
|
||||
|
||||
if (value != dst.opentherm.immergasFix) {
|
||||
dst.opentherm.immergasFix = value;
|
||||
if (value != dst.opentherm.options.immergasFix) {
|
||||
dst.opentherm.options.immergasFix = value;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -923,7 +955,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
||||
if (src[FPSTR(S_EQUITHERM)][FPSTR(S_ENABLED)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_EQUITHERM)][FPSTR(S_ENABLED)].as<bool>();
|
||||
|
||||
if (!dst.opentherm.nativeHeatingControl) {
|
||||
if (!dst.opentherm.options.nativeHeatingControl) {
|
||||
if (value != dst.equitherm.enabled) {
|
||||
dst.equitherm.enabled = value;
|
||||
changed = true;
|
||||
@@ -967,7 +999,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
||||
if (src[FPSTR(S_PID)][FPSTR(S_ENABLED)].is<bool>()) {
|
||||
bool value = src[FPSTR(S_PID)][FPSTR(S_ENABLED)].as<bool>();
|
||||
|
||||
if (!dst.opentherm.nativeHeatingControl) {
|
||||
if (!dst.opentherm.options.nativeHeatingControl) {
|
||||
if (value != dst.pid.enabled) {
|
||||
dst.pid.enabled = value;
|
||||
changed = true;
|
||||
@@ -1326,7 +1358,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
||||
// force check emergency target
|
||||
{
|
||||
float value = !src[FPSTR(S_EMERGENCY)][FPSTR(S_TARGET)].isNull() ? src[FPSTR(S_EMERGENCY)][FPSTR(S_TARGET)].as<float>() : dst.emergency.target;
|
||||
bool noRegulators = !dst.opentherm.nativeHeatingControl;
|
||||
bool noRegulators = !dst.opentherm.options.nativeHeatingControl;
|
||||
bool valid = isValidTemp(
|
||||
value,
|
||||
dst.system.unitSystem,
|
||||
@@ -1351,7 +1383,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
||||
|
||||
// force check heating target
|
||||
{
|
||||
bool indoorTempControl = dst.equitherm.enabled || dst.pid.enabled || dst.opentherm.nativeHeatingControl;
|
||||
bool indoorTempControl = dst.equitherm.enabled || dst.pid.enabled || dst.opentherm.options.nativeHeatingControl;
|
||||
float minTemp = indoorTempControl ? THERMOSTAT_INDOOR_MIN_TEMP : dst.heating.minTemp;
|
||||
float maxTemp = indoorTempControl ? THERMOSTAT_INDOOR_MAX_TEMP : dst.heating.maxTemp;
|
||||
|
||||
@@ -1720,6 +1752,7 @@ void varsToJson(const Variables& src, JsonVariant dst) {
|
||||
slave[FPSTR(S_PROTOCOL_VERSION)] = src.slave.appVersion;
|
||||
slave[FPSTR(S_CONNECTED)] = src.slave.connected;
|
||||
slave[FPSTR(S_FLAME)] = src.slave.flame;
|
||||
slave[FPSTR(S_COOLING)] = src.slave.cooling;
|
||||
|
||||
auto sModulation = slave[FPSTR(S_MODULATION)].to<JsonObject>();
|
||||
sModulation[FPSTR(S_MIN)] = src.slave.modulation.min;
|
||||
|
||||
@@ -87,6 +87,18 @@
|
||||
"turbo": "Turbo mode"
|
||||
},
|
||||
|
||||
"notify": {
|
||||
"fault": {
|
||||
"title": "Boiler Fault state is active!",
|
||||
"note": "It is recommended to inspect the boiler and study the documentation to interpret the fault code:"
|
||||
},
|
||||
"diag": {
|
||||
"title": "Boiler Diagnostic state is active!",
|
||||
"note": "Perhaps your boiler needs inspection? It is recommended study the documentation to interpret the diag code:"
|
||||
},
|
||||
"reset": "Try reset"
|
||||
},
|
||||
|
||||
"states": {
|
||||
"mNetworkConnected": "Network connection",
|
||||
"mMqttConnected": "MQTT connection",
|
||||
@@ -97,8 +109,9 @@
|
||||
|
||||
"sConnected": "OpenTherm connection",
|
||||
"sFlame": "Flame",
|
||||
"sCooling": "Cooling",
|
||||
"sFaultActive": "Fault",
|
||||
"sFaultCode": "Faul code",
|
||||
"sFaultCode": "Fault code",
|
||||
"sDiagActive": "Diagnostic",
|
||||
"sDiagCode": "Diagnostic code",
|
||||
|
||||
@@ -356,13 +369,16 @@
|
||||
|
||||
"options": {
|
||||
"desc": "Options",
|
||||
"dhwPresent": "DHW present",
|
||||
"dhwSupport": "DHW support",
|
||||
"coolingSupport": "Cooling support",
|
||||
"summerWinterMode": "Summer/winter mode",
|
||||
"heatingCh2Enabled": "Heating CH2 always enabled",
|
||||
"heatingCh1ToCh2": "Duplicate heating CH1 to CH2",
|
||||
"heatingStateToSummerWinterMode": "Heating state as summer/winter mode",
|
||||
"ch2AlwaysEnabled": "CH2 always enabled",
|
||||
"heatingToCh2": "Duplicate heating to CH2",
|
||||
"dhwToCh2": "Duplicate DHW to CH2",
|
||||
"dhwBlocking": "DHW blocking",
|
||||
"modulationSyncWithHeating": "Sync modulation with heating",
|
||||
"maxTempSyncWithTargetTemp": "Sync max heating temp with target temp",
|
||||
"getMinMaxTemp": "Get min/max temp from boiler",
|
||||
"immergasFix": "Fix for Immergas boilers"
|
||||
},
|
||||
|
||||
@@ -87,6 +87,18 @@
|
||||
"turbo": "Турбо"
|
||||
},
|
||||
|
||||
"notify": {
|
||||
"fault": {
|
||||
"title": "Состояние неисправности котла активно!",
|
||||
"note": "Рекомендуется осмотреть котел и изучить документацию котла для расшифровки кода неисправности:"
|
||||
},
|
||||
"diag": {
|
||||
"title": "Состояние диагностики котла активно!",
|
||||
"note": "Возможно, вашему котлу требуется проверка? Рекомендуется изучить документацию котла для расшифровки кода диагностики:"
|
||||
},
|
||||
"reset": "Сбросить"
|
||||
},
|
||||
|
||||
"states": {
|
||||
"mNetworkConnected": "Подключение к сети",
|
||||
"mMqttConnected": "Подключение к MQTT",
|
||||
@@ -97,6 +109,7 @@
|
||||
|
||||
"sConnected": "Подключение к OpenTherm",
|
||||
"sFlame": "Пламя",
|
||||
"sCooling": "Охлаждение",
|
||||
"sFaultActive": "Ошибка",
|
||||
"sFaultCode": "Код ошибки",
|
||||
"sDiagActive": "Диагностика",
|
||||
@@ -180,7 +193,7 @@
|
||||
"purpose": "Назначение",
|
||||
"purposes": {
|
||||
"outdoorTemp": "Внешняя температура",
|
||||
"indoorTemp": "Внутреняя температура",
|
||||
"indoorTemp": "Внутренняя температура",
|
||||
"heatTemp": "Отопление, температура",
|
||||
"heatRetTemp": "Отопление, температура обратки",
|
||||
"dhwTemp": "ГВС, температура",
|
||||
@@ -356,13 +369,16 @@
|
||||
|
||||
"options": {
|
||||
"desc": "Опции",
|
||||
"dhwPresent": "Контур ГВС",
|
||||
"dhwSupport": "Поддержка ГВС",
|
||||
"coolingSupport": "Поддержка охлаждения",
|
||||
"summerWinterMode": "Летний/зимний режим",
|
||||
"heatingCh2Enabled": "Канал 2 отопления всегда вкл.",
|
||||
"heatingCh1ToCh2": "Дублировать параметры отопления канала 1 в канал 2",
|
||||
"heatingStateToSummerWinterMode": "Летний/зимний режим в качестве состояния отопления",
|
||||
"ch2AlwaysEnabled": "Канал 2 всегда вкл.",
|
||||
"heatingToCh2": "Дублировать параметры отопления в канал 2",
|
||||
"dhwToCh2": "Дублировать параметры ГВС в канал 2",
|
||||
"dhwBlocking": "DHW blocking",
|
||||
"modulationSyncWithHeating": "Синхронизировать модуляцию с отоплением",
|
||||
"maxTempSyncWithTargetTemp": "Синхронизировать макс. темп. отопления с целевой темп.",
|
||||
"getMinMaxTemp": "Получать мин. и макс. температуру от котла",
|
||||
"immergasFix": "Фикс для котлов Immergas"
|
||||
},
|
||||
|
||||
@@ -71,6 +71,36 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="notify notify-error notify-fault hidden">
|
||||
<div class="notify-icon">
|
||||
<i class="icons-error"></i>
|
||||
</div>
|
||||
<div class="notify-content">
|
||||
<b data-i18n>dashboard.notify.fault.title</b><br />
|
||||
<small>
|
||||
<span data-i18n>dashboard.notify.fault.note</span> <b class="sFaultCode"></b>
|
||||
</small>
|
||||
</div>
|
||||
<div class="notify-actions">
|
||||
<button class="reset" data-i18n>dashboard.notify.reset</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="notify notify-alarm notify-diag hidden">
|
||||
<div class="notify-icon">
|
||||
<i class="icons-alarm"></i>
|
||||
</div>
|
||||
<div class="notify-content">
|
||||
<b data-i18n>dashboard.notify.diag.title</b><br />
|
||||
<small>
|
||||
<span data-i18n>dashboard.notify.diag.note</span> <b class="sDiagCode"></b>
|
||||
</small>
|
||||
</div>
|
||||
<div class="notify-actions">
|
||||
<button class="reset" data-i18n>dashboard.notify.reset</button>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<hr />
|
||||
@@ -113,6 +143,10 @@
|
||||
<th scope="row" data-i18n>dashboard.states.sFlame</th>
|
||||
<td><i class="sFlame"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.states.sCooling</th>
|
||||
<td><i class="sCooling"></i></td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
@@ -354,6 +388,60 @@
|
||||
newSettings.dhw.enabled = event.currentTarget.checked;
|
||||
});
|
||||
|
||||
document.querySelector('.notify-fault .reset').addEventListener('click', async (event) => {
|
||||
const resetBtn = document.querySelector(".notify-fault .reset");
|
||||
if (!resetBtn.disabled) {
|
||||
resetBtn.disabled = true;
|
||||
}
|
||||
|
||||
let response = await fetch("/api/vars", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"actions": {
|
||||
"resetFault": true
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
if (resetBtn.disabled) {
|
||||
resetBtn.disabled = false;
|
||||
}
|
||||
}, 10000);
|
||||
});
|
||||
|
||||
document.querySelector('.notify-diag .reset').addEventListener('click', async (event) => {
|
||||
const resetBtn = document.querySelector(".notify-diag .reset");
|
||||
if (!resetBtn.disabled) {
|
||||
resetBtn.disabled = true;
|
||||
}
|
||||
|
||||
let response = await fetch("/api/vars", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"actions": {
|
||||
"resetDiagnostic": true
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
if (resetBtn.disabled) {
|
||||
resetBtn.disabled = false;
|
||||
}
|
||||
}, 10000);
|
||||
});
|
||||
|
||||
setTimeout(async function onLoadPage() {
|
||||
let unitSystem = null;
|
||||
|
||||
@@ -372,8 +460,8 @@
|
||||
(prevSettings.heating.enabled != newSettings.heating.enabled)
|
||||
|| (prevSettings.heating.turbo != newSettings.heating.turbo)
|
||||
|| (prevSettings.heating.target != newSettings.heating.target)
|
||||
|| (prevSettings.opentherm.dhwPresent && prevSettings.dhw.enabled != newSettings.dhw.enabled)
|
||||
|| (prevSettings.opentherm.dhwPresent && prevSettings.dhw.target != newSettings.dhw.target)
|
||||
|| (prevSettings.opentherm.options.dhwSupport && prevSettings.dhw.enabled != newSettings.dhw.enabled)
|
||||
|| (prevSettings.opentherm.options.dhwSupport && prevSettings.dhw.target != newSettings.dhw.target)
|
||||
);
|
||||
|
||||
if (modified) {
|
||||
@@ -397,7 +485,7 @@
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
noRegulators = !result.opentherm.nativeHeatingControl && !result.equitherm.enabled && !result.pid.enabled;
|
||||
noRegulators = !result.opentherm.options.nativeHeatingControl && !result.equitherm.enabled && !result.pid.enabled;
|
||||
prevSettings = result;
|
||||
unitSystem = result.system.unitSystem;
|
||||
newSettings.heating.enabled = result.heating.enabled;
|
||||
@@ -406,7 +494,7 @@
|
||||
newSettings.dhw.enabled = result.dhw.enabled;
|
||||
newSettings.dhw.target = result.dhw.target;
|
||||
|
||||
if (result.opentherm.dhwPresent) {
|
||||
if (result.opentherm.options.dhwSupport) {
|
||||
show('#thermostat-dhw');
|
||||
} else {
|
||||
hide('#thermostat-dhw');
|
||||
@@ -462,6 +550,7 @@
|
||||
result.slave.connected ? "green" : "red"
|
||||
);
|
||||
setState('.sFlame', result.slave.flame);
|
||||
setState('.sCooling', result.slave.cooling);
|
||||
|
||||
setValue('.sModMin', result.slave.modulation.min);
|
||||
setValue('.sModMax', result.slave.modulation.max);
|
||||
@@ -489,6 +578,13 @@
|
||||
: "-"
|
||||
);
|
||||
|
||||
if (result.slave.fault.active) {
|
||||
show(".notify-fault");
|
||||
|
||||
} else {
|
||||
hide('.notify-fault');
|
||||
}
|
||||
|
||||
setStatus(
|
||||
'.sDiagActive',
|
||||
result.slave.diag.active ? "success" : "error",
|
||||
@@ -501,6 +597,13 @@
|
||||
: "-"
|
||||
);
|
||||
|
||||
if (result.slave.diag.active) {
|
||||
show(".notify-diag");
|
||||
|
||||
} else {
|
||||
hide('.notify-diag');
|
||||
}
|
||||
|
||||
|
||||
// MASTER
|
||||
setState('.mHeatEnabled', result.master.heating.enabled);
|
||||
|
||||
@@ -38,37 +38,37 @@
|
||||
|
||||
<div id="network-settings-busy" aria-busy="true"></div>
|
||||
<form action="/api/network/settings" id="network-settings" class="hidden">
|
||||
<label for="network-hostname">
|
||||
<label>
|
||||
<span data-i18n>network.params.hostname</span>
|
||||
<input type="text" id="network-hostname" name="hostname" maxlength="24" pattern="[A-Za-z0-9]+[A-Za-z0-9\-]+[A-Za-z0-9]+" required>
|
||||
<input type="text" 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">
|
||||
<label>
|
||||
<input type="checkbox" name="useDhcp" value="true">
|
||||
<span data-i18n>network.params.dhcp</span>
|
||||
</label>
|
||||
<br />
|
||||
<hr />
|
||||
<h4 data-i18n>network.section.static</h4>
|
||||
|
||||
<label for="network-static-ip">
|
||||
<label>
|
||||
<span data-i18n>network.params.ip</span>
|
||||
<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>
|
||||
<input type="text" 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">
|
||||
<label>
|
||||
<span data-i18n>network.params.gateway</span>
|
||||
<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>
|
||||
<input type="text" 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">
|
||||
<label>
|
||||
<span data-i18n>network.params.subnet</span>
|
||||
<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>
|
||||
<input type="text" 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">
|
||||
<label>
|
||||
<span data-i18n>network.params.dns</span>
|
||||
<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>
|
||||
<input type="text" name="staticConfig[dns]" maxlength="16" pattern="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" required>
|
||||
</label>
|
||||
|
||||
<button type="submit" data-i18n>button.save</button>
|
||||
@@ -109,19 +109,19 @@
|
||||
|
||||
<div id="sta-settings-busy" aria-busy="true"></div>
|
||||
<form action="/api/network/settings" id="sta-settings" class="hidden">
|
||||
<label for="sta-ssid">
|
||||
<label>
|
||||
<span data-i18n>network.wifi.ssid</span>
|
||||
<input type="text" id="sta-ssid" name="sta[ssid]" maxlength="32" required>
|
||||
<input type="text" name="sta[ssid]" maxlength="32" required>
|
||||
</label>
|
||||
|
||||
<label for="sta-password">
|
||||
<label>
|
||||
<span data-i18n>network.wifi.password</span>
|
||||
<input type="password" id="sta-password" name="sta[password]" maxlength="64" required>
|
||||
<input type="password" name="sta[password]" maxlength="64" required>
|
||||
</label>
|
||||
|
||||
<label for="sta-channel">
|
||||
<label>
|
||||
<span data-i18n>network.wifi.channel</span>
|
||||
<input type="number" inputmode="numeric" id="sta-channel" name="sta[channel]" min="0" max="12" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="sta[channel]" min="0" max="12" step="1" required>
|
||||
<small data-i18n>network.sta.channel.note</small>
|
||||
</label>
|
||||
|
||||
@@ -140,19 +140,19 @@
|
||||
|
||||
<div id="ap-settings-busy" aria-busy="true"></div>
|
||||
<form action="/api/network/settings" id="ap-settings" class="hidden">
|
||||
<label for="ap-ssid">
|
||||
<label>
|
||||
<span data-i18n>network.wifi.ssid</span>
|
||||
<input type="text" id="ap-ssid" name="ap[ssid]" maxlength="32" required>
|
||||
<input type="text" name="ap[ssid]" maxlength="32" required>
|
||||
</label>
|
||||
|
||||
<label for="ap-password">
|
||||
<label>
|
||||
<span data-i18n>network.wifi.password</span>
|
||||
<input type="text" id="ap-password" name="ap[password]" maxlength="64" required>
|
||||
<input type="text" name="ap[password]" maxlength="64" required>
|
||||
</label>
|
||||
|
||||
<label for="ap-channel">
|
||||
<label>
|
||||
<span data-i18n>network.wifi.channel</span>
|
||||
<input type="number" inputmode="numeric" id="ap-channel" name="ap[channel]" min="1" max="12" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="ap[channel]" min="1" max="12" step="1" required>
|
||||
</label>
|
||||
|
||||
<button type="submit" data-i18n>button.save</button>
|
||||
@@ -179,22 +179,22 @@
|
||||
lang.build();
|
||||
|
||||
const fillData = (data) => {
|
||||
setInputValue('#network-hostname', data.hostname);
|
||||
setCheckboxValue('#network-use-dhcp', data.useDhcp);
|
||||
setInputValue('#network-static-ip', data.staticConfig.ip);
|
||||
setInputValue('#network-static-gateway', data.staticConfig.gateway);
|
||||
setInputValue('#network-static-subnet', data.staticConfig.subnet);
|
||||
setInputValue('#network-static-dns', data.staticConfig.dns);
|
||||
setInputValue("[name='hostname']", data.hostname);
|
||||
setCheckboxValue("[name='useDhcp']", data.useDhcp);
|
||||
setInputValue("[name='staticConfig[ip]']", data.staticConfig.ip);
|
||||
setInputValue("[name='staticConfig[gateway]']", data.staticConfig.gateway);
|
||||
setInputValue("[name='staticConfig[subnet]']", data.staticConfig.subnet);
|
||||
setInputValue("[name='staticConfig[dns]']", data.staticConfig.dns);
|
||||
setBusy('#network-settings-busy', '#network-settings', false);
|
||||
|
||||
setInputValue('#sta-ssid', data.sta.ssid);
|
||||
setInputValue('#sta-password', data.sta.password);
|
||||
setInputValue('#sta-channel', data.sta.channel);
|
||||
setInputValue("[name='sta[ssid]']", data.sta.ssid);
|
||||
setInputValue("[name='sta[password]']", data.sta.password);
|
||||
setInputValue("[name='sta[channel]']", data.sta.channel);
|
||||
setBusy('#sta-settings-busy', '#sta-settings', false);
|
||||
|
||||
setInputValue('#ap-ssid', data.ap.ssid);
|
||||
setInputValue('#ap-password', data.ap.password);
|
||||
setInputValue('#ap-channel', data.ap.channel);
|
||||
setInputValue("[name='ap[ssid]']", data.ap.ssid);
|
||||
setInputValue("[name='ap[password]']", data.ap.password);
|
||||
setInputValue("[name='ap[channel]']", data.ap.channel);
|
||||
setBusy('#ap-settings-busy', '#ap-settings', false);
|
||||
};
|
||||
|
||||
|
||||
@@ -134,12 +134,12 @@
|
||||
<div class="grid">
|
||||
<label>
|
||||
<span data-i18n>sensors.correction.offset</span>
|
||||
<input type="number" inputmode="numeric" name="offset" min="-20" max="20" step="0.01" required>
|
||||
<input type="number" inputmode="decimal" name="offset" min="-20" max="20" step="0.01" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span data-i18n>sensors.correction.factor</span>
|
||||
<input type="number" inputmode="numeric" name="factor" min="0.01" max="10" step="0.01" required>
|
||||
<input type="number" inputmode="decimal" name="factor" min="0.01" max="10" step="0.01" required>
|
||||
</label>
|
||||
</div>
|
||||
</details>
|
||||
@@ -159,7 +159,7 @@
|
||||
|
||||
<label>
|
||||
<span data-i18n>sensors.filtering.factor.title</span>
|
||||
<input type="number" inputmode="numeric" name="filteringFactor" min="0.01" max="1" step="0.01">
|
||||
<input type="number" inputmode="decimal" name="filteringFactor" min="0.01" max="1" step="0.01">
|
||||
<small data-i18n>sensors.filtering.factor.note</small>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -41,19 +41,19 @@
|
||||
<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">
|
||||
<label>
|
||||
<span data-i18n>settings.portal.login</span>
|
||||
<input type="text" id="portal-login" name="portal[login]" maxlength="12" required>
|
||||
<input type="text" name="portal[login]" maxlength="12" required>
|
||||
</label>
|
||||
|
||||
<label for="portal-password">
|
||||
<label>
|
||||
<span data-i18n>settings.portal.password</span>
|
||||
<input type="password" id="portal-password" name="portal[password]" maxlength="32" required>
|
||||
<input type="password" name="portal[password]" maxlength="32" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label for="portal-auth">
|
||||
<input type="checkbox" id="portal-auth" name="portal[auth]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="portal[auth]" value="true">
|
||||
<span data-i18n>settings.portal.auth</span>
|
||||
</label>
|
||||
<br />
|
||||
@@ -74,20 +74,20 @@
|
||||
<legend data-i18n>settings.system.unit</legend>
|
||||
|
||||
<label>
|
||||
<input type="radio" class="system-unit-system" name="system[unitSystem]" value="0" />
|
||||
<input type="radio" name="system[unitSystem]" value="0" />
|
||||
<span data-i18n>settings.system.metric</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input type="radio" class="system-unit-system" name="system[unitSystem]" value="1" />
|
||||
<input type="radio" name="system[unitSystem]" value="1" />
|
||||
<span data-i18n>settings.system.imperial</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="system-status-led-gpio">
|
||||
<label>
|
||||
<span data-i18n>settings.system.statusLedGpio</span>
|
||||
<input type="number" inputmode="numeric" id="system-status-led-gpio" name="system[statusLedGpio]" min="0" max="254" step="1">
|
||||
<input type="number" inputmode="numeric" name="system[statusLedGpio]" min="0" max="254" step="1">
|
||||
<small data-i18n>settings.note.blankNotUse</small>
|
||||
</label>
|
||||
</fieldset>
|
||||
@@ -95,19 +95,19 @@
|
||||
<fieldset>
|
||||
<legend data-i18n>settings.section.diag</legend>
|
||||
|
||||
<label for="system-serial-enable">
|
||||
<input type="checkbox" id="system-serial-enable" name="system[serial][enabled]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="system[serial][enabled]" value="true">
|
||||
<span data-i18n>settings.system.serial.enable</span>
|
||||
</label>
|
||||
|
||||
<label for="system-telnet-enable">
|
||||
<input type="checkbox" id="system-telnet-enable" name="system[telnet][enabled]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="system[telnet][enabled]" value="true">
|
||||
<span data-i18n>settings.system.telnet.enable</span>
|
||||
</label>
|
||||
|
||||
<label for="system-log-level">
|
||||
<label>
|
||||
<span data-i18n>settings.system.logLevel</span>
|
||||
<select id="system-log-level" name="system[logLevel]">
|
||||
<select name="system[logLevel]">
|
||||
<option value="0">SILENT</option>
|
||||
<option value="1">FATAL</option>
|
||||
<option value="2">ERROR</option>
|
||||
@@ -120,9 +120,9 @@
|
||||
</label>
|
||||
|
||||
<div class="grid">
|
||||
<label for="system-serial-baudrate">
|
||||
<label>
|
||||
<span data-i18n>settings.system.serial.baud</span>
|
||||
<select id="system-serial-baudrate" name="system[serial][baudrate]" required>
|
||||
<select name="system[serial][baudrate]" required>
|
||||
<option value="9600">9600</option>
|
||||
<option value="19200">19200</option>
|
||||
<option value="38400">38400</option>
|
||||
@@ -132,9 +132,9 @@
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label for="system-telnet-port">
|
||||
<label>
|
||||
<span data-i18n>settings.system.telnet.port.title</span>
|
||||
<input type="number" inputmode="numeric" id="system-telnet-port" name="system[telnet][port]" min="1" max="65535" step="1" required>
|
||||
<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>
|
||||
@@ -156,26 +156,26 @@
|
||||
<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">
|
||||
<label>
|
||||
<span data-i18n>settings.temp.min</span>
|
||||
<input type="number" inputmode="numeric" id="heating-min-temp" name="heating[minTemp]" min="0" max="0" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="heating[minTemp]" min="0" max="0" step="1" required>
|
||||
</label>
|
||||
|
||||
<label for="heating-max-temp">
|
||||
<label>
|
||||
<span data-i18n>settings.temp.max</span>
|
||||
<input type="number" inputmode="numeric" id="heating-max-temp" name="heating[maxTemp]" min="0" max="0" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="heating[maxTemp]" min="0" max="0" step="1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<label for="heating-hysteresis">
|
||||
<label>
|
||||
<span data-i18n>settings.heating.hyst</span>
|
||||
<input type="number" inputmode="numeric" id="heating-hysteresis" name="heating[hysteresis]" min="0" max="5" step="0.05" required>
|
||||
<input type="number" inputmode="decimal" name="heating[hysteresis]" min="0" max="5" step="0.05" required>
|
||||
</label>
|
||||
|
||||
<label for="heating-turbo-factor">
|
||||
<label>
|
||||
<span data-i18n>settings.heating.turboFactor</span>
|
||||
<input type="number" inputmode="numeric" id="heating-turbo-factor" name="heating[turboFactor]" min="1.5" max="10" step="0.1" required>
|
||||
<input type="number" inputmode="decimal" name="heating[turboFactor]" min="1.5" max="10" step="0.1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -192,14 +192,14 @@
|
||||
<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">
|
||||
<label>
|
||||
<span data-i18n>settings.temp.min</span>
|
||||
<input type="number" inputmode="numeric" id="dhw-min-temp" name="dhw[minTemp]" min="0" max="0" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="dhw[minTemp]" min="0" max="0" step="1" required>
|
||||
</label>
|
||||
|
||||
<label for="dhw-max-temp">
|
||||
<label>
|
||||
<span data-i18n>settings.temp.max</span>
|
||||
<input type="number" inputmode="numeric" id="dhw-max-temp" name="dhw[maxTemp]" min="0" max="0" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="dhw[maxTemp]" min="0" max="0" step="1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -220,15 +220,15 @@
|
||||
</fieldset>
|
||||
|
||||
<div class="grid">
|
||||
<label for="emergency-target">
|
||||
<label>
|
||||
<span data-i18n>settings.emergency.target.title</span>
|
||||
<input type="number" inputmode="numeric" id="emergency-target" name="emergency[target]" min="0" max="0" step="1" required>
|
||||
<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 for="emergency-treshold-time">
|
||||
<label>
|
||||
<span data-i18n>settings.emergency.treshold</span>
|
||||
<input type="number" inputmode="numeric" id="emergency-treshold-time" name="emergency[tresholdTime]" min="60" max="1800" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="emergency[tresholdTime]" min="60" max="1800" step="1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -245,26 +245,26 @@
|
||||
<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[enabled]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="equitherm[enabled]" value="true">
|
||||
<span data-i18n>settings.enable</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="grid">
|
||||
<label for="equitherm-n-factor">
|
||||
<label>
|
||||
<span data-i18n>settings.equitherm.n</span>
|
||||
<input type="number" inputmode="numeric" id="equitherm-n-factor" name="equitherm[n_factor]" min="0.001" max="10" step="0.001" required>
|
||||
<input type="number" inputmode="decimal" name="equitherm[n_factor]" min="0.001" max="10" step="0.001" required>
|
||||
</label>
|
||||
|
||||
<label for="equitherm-k-factor">
|
||||
<label>
|
||||
<span data-i18n>settings.equitherm.k</span>
|
||||
<input type="number" inputmode="numeric" id="equitherm-k-factor" name="equitherm[k_factor]" min="0" max="10" step="0.01" required>
|
||||
<input type="number" inputmode="decimal" name="equitherm[k_factor]" min="0" max="10" step="0.01" required>
|
||||
</label>
|
||||
|
||||
<label for="equitherm-t-factor">
|
||||
<label>
|
||||
<span data-i18n>settings.equitherm.t.title</span>
|
||||
<input type="number" inputmode="numeric" id="equitherm-t-factor" name="equitherm[t_factor]" min="0" max="10" step="0.01" required>
|
||||
<input type="number" inputmode="decimal" name="equitherm[t_factor]" min="0" max="10" step="0.01" required>
|
||||
<small data-i18n>settings.equitherm.t.note</small>
|
||||
</label>
|
||||
</div>
|
||||
@@ -282,45 +282,45 @@
|
||||
<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[enabled]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="pid[enabled]" value="true">
|
||||
<span data-i18n>settings.enable</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="grid">
|
||||
<label for="pid-p-factor">
|
||||
<label>
|
||||
<span data-i18n>settings.pid.p</span>
|
||||
<input type="number" inputmode="numeric" id="pid-p-factor" name="pid[p_factor]" min="0.1" max="1000" step="0.01" required>
|
||||
<input type="number" inputmode="decimal" name="pid[p_factor]" min="0.1" max="1000" step="0.01" required>
|
||||
</label>
|
||||
|
||||
<label for="pid-i-factor">
|
||||
<label>
|
||||
<span data-i18n>settings.pid.i</span>
|
||||
<input type="number" inputmode="numeric" id="pid-i-factor" name="pid[i_factor]" min="0" max="100" step="0.0001" required>
|
||||
<input type="number" inputmode="decimal" name="pid[i_factor]" min="0" max="100" step="0.0001" required>
|
||||
</label>
|
||||
|
||||
<label for="pid-d-factor">
|
||||
<label>
|
||||
<span data-i18n>settings.pid.d</span>
|
||||
<input type="number" inputmode="numeric" id="pid-d-factor" name="pid[d_factor]" min="0" max="100000" step="0.1" required>
|
||||
<input type="number" inputmode="decimal" name="pid[d_factor]" min="0" max="100000" step="0.1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label for="pid-dt">
|
||||
<label>
|
||||
<span data-i18n>settings.pid.dt</span>
|
||||
<input type="number" inputmode="numeric" id="pid-dt" name="pid[dt]" min="30" max="1800" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="pid[dt]" min="30" max="1800" step="1" required>
|
||||
</label>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="grid">
|
||||
<label for="pid-min-temp">
|
||||
<label>
|
||||
<span data-i18n>settings.temp.min</span>
|
||||
<input type="number" inputmode="numeric" id="pid-min-temp" name="pid[minTemp]" min="0" max="0" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="pid[minTemp]" min="0" max="0" step="1" required>
|
||||
</label>
|
||||
|
||||
<label for="pid-max-temp">
|
||||
<label>
|
||||
<span data-i18n>settings.temp.max</span>
|
||||
<input type="number" inputmode="numeric" id="pid-max-temp" name="pid[maxTemp]" min="0" max="0" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="pid[maxTemp]" min="0" max="0" step="1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -336,67 +336,67 @@
|
||||
<details>
|
||||
<summary><b data-i18n>settings.section.ot</b></summary>
|
||||
<div>
|
||||
<div id="opentherm-settings-busy" aria-busy="true"></div>
|
||||
<form action="/api/settings" id="opentherm-settings" class="hidden">
|
||||
<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" class="opentherm-unit-system" name="opentherm[unitSystem]" value="0" />
|
||||
<input type="radio" name="opentherm[unitSystem]" value="0" />
|
||||
<span data-i18n>settings.system.metric</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input type="radio" class="opentherm-unit-system" name="opentherm[unitSystem]" value="1" />
|
||||
<input type="radio" name="opentherm[unitSystem]" value="1" />
|
||||
<span data-i18n>settings.system.imperial</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="grid">
|
||||
<label for="opentherm-in-gpio">
|
||||
<label>
|
||||
<span data-i18n>settings.ot.inGpio</span>
|
||||
<input type="number" inputmode="numeric" id="opentherm-in-gpio" name="opentherm[inGpio]" min="0" max="254" step="1">
|
||||
<input type="number" inputmode="numeric" name="opentherm[inGpio]" min="0" max="254" step="1">
|
||||
</label>
|
||||
|
||||
<label for="opentherm-in-gpio">
|
||||
<label>
|
||||
<span data-i18n>settings.ot.outGpio</span>
|
||||
<input type="number" inputmode="numeric" id="opentherm-out-gpio" name="opentherm[outGpio]" min="0" max="254" step="1">
|
||||
<input type="number" inputmode="numeric" name="opentherm[outGpio]" min="0" max="254" step="1">
|
||||
</label>
|
||||
|
||||
<label for="opentherm-rx-led-gpio">
|
||||
<label>
|
||||
<span data-i18n>settings.ot.ledGpio</span>
|
||||
<input type="number" inputmode="numeric" id="opentherm-rx-led-gpio" name="opentherm[rxLedGpio]" min="0" max="254" step="1">
|
||||
<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 for="opentherm-member-id-code">
|
||||
<label>
|
||||
<span data-i18n>settings.ot.memberId</span>
|
||||
<input type="number" inputmode="numeric" id="opentherm-member-id" name="opentherm[memberId]" min="0" max="255" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="opentherm[memberId]" min="0" max="255" step="1" required>
|
||||
</label>
|
||||
|
||||
<label for="opentherm-flags">
|
||||
<label>
|
||||
<span data-i18n>settings.ot.flags</span>
|
||||
<input type="number" inputmode="numeric" id="opentherm-flags" name="opentherm[flags]" min="0" max="255" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="opentherm[flags]" min="0" max="255" step="1" required>
|
||||
</label>
|
||||
|
||||
<label for="opentherm-max-modulation">
|
||||
<label>
|
||||
<span data-i18n>settings.ot.maxMod</span>
|
||||
<input type="number" inputmode="numeric" id="opentherm-max-modulation" name="opentherm[maxModulation]" min="1" max="100" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="opentherm[maxModulation]" min="1" max="100" step="1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<label for="opentherm-min-power">
|
||||
<label>
|
||||
<span data-i18n>settings.ot.minPower.title</span>
|
||||
<input type="number" inputmode="numeric" id="opentherm-min-power" name="opentherm[minPower]" min="0" max="1000" step="0.1">
|
||||
<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 for="opentherm-max-power">
|
||||
<label>
|
||||
<span data-i18n>settings.ot.maxPower.title</span>
|
||||
<input type="number" inputmode="numeric" id="opentherm-max-power" name="opentherm[maxPower]" min="0" max="1000" step="0.1">
|
||||
<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>
|
||||
@@ -404,54 +404,69 @@
|
||||
<fieldset>
|
||||
<legend data-i18n>settings.ot.options.desc</legend>
|
||||
|
||||
<label for="opentherm-dhw-present">
|
||||
<input type="checkbox" id="opentherm-dhw-present" name="opentherm[dhwPresent]" value="true">
|
||||
<span data-i18n>settings.ot.options.dhwPresent</span>
|
||||
<label>
|
||||
<input type="checkbox" name="opentherm[options][dhwSupport]" value="true">
|
||||
<span data-i18n>settings.ot.options.dhwSupport</span>
|
||||
</label>
|
||||
|
||||
<label for="opentherm-sw-mode">
|
||||
<input type="checkbox" id="opentherm-sw-mode" name="opentherm[summerWinterMode]" value="true">
|
||||
<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 for="opentherm-heating-ch2-enabled">
|
||||
<input type="checkbox" id="opentherm-heating-ch2-enabled" name="opentherm[heatingCh2Enabled]" value="true">
|
||||
<span data-i18n>settings.ot.options.heatingCh2Enabled</span>
|
||||
<label>
|
||||
<input type="checkbox" name="opentherm[options][heatingStateToSummerWinterMode]" value="true">
|
||||
<span data-i18n>settings.ot.options.heatingStateToSummerWinterMode</span>
|
||||
</label>
|
||||
|
||||
<label for="opentherm-heating-ch1-to-ch2">
|
||||
<input type="checkbox" id="opentherm-heating-ch1-to-ch2" name="opentherm[heatingCh1ToCh2]" value="true">
|
||||
<span data-i18n>settings.ot.options.heatingCh1ToCh2</span>
|
||||
<label>
|
||||
<input type="checkbox" name="opentherm[options][ch2AlwaysEnabled]" value="true">
|
||||
<span data-i18n>settings.ot.options.ch2AlwaysEnabled</span>
|
||||
</label>
|
||||
|
||||
<label for="opentherm-dhw-to-ch2">
|
||||
<input type="checkbox" id="opentherm-dhw-to-ch2" name="opentherm[dhwToCh2]" value="true">
|
||||
<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 for="opentherm-dhw-blocking">
|
||||
<input type="checkbox" id="opentherm-dhw-blocking" name="opentherm[dhwBlocking]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="opentherm[options][dhwBlocking]" value="true">
|
||||
<span data-i18n>settings.ot.options.dhwBlocking</span>
|
||||
</label>
|
||||
|
||||
<label for="opentherm-sync-modulation-with-heating">
|
||||
<input type="checkbox" id="opentherm-sync-modulation-with-heating" name="opentherm[modulationSyncWithHeating]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="opentherm[options][modulationSyncWithHeating]" value="true">
|
||||
<span data-i18n>settings.ot.options.modulationSyncWithHeating</span>
|
||||
</label>
|
||||
|
||||
<label for="opentherm-get-min-max-temp">
|
||||
<input type="checkbox" id="opentherm-get-min-max-temp" name="opentherm[getMinMaxTemp]" value="true">
|
||||
<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 for="opentherm-immergas-fix">
|
||||
<input type="checkbox" id="opentherm-immergas-fix" name="opentherm[immergasFix]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="opentherm[options][immergasFix]" value="true">
|
||||
<span data-i18n>settings.ot.options.immergasFix</span>
|
||||
</label>
|
||||
|
||||
<hr />
|
||||
<label for="opentherm-native-heating-control">
|
||||
<input type="checkbox" id="opentherm-native-heating-control" name="opentherm[nativeHeatingControl]" value="true">
|
||||
<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>
|
||||
@@ -470,50 +485,50 @@
|
||||
<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[enabled]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="mqtt[enabled]" value="true">
|
||||
<span data-i18n>settings.enable</span>
|
||||
</label>
|
||||
|
||||
<label for="mqtt-ha-discovery">
|
||||
<input type="checkbox" id="mqtt-ha-discovery" name="mqtt[homeAssistantDiscovery]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="mqtt[homeAssistantDiscovery]" value="true">
|
||||
<span data-i18n>settings.mqtt.homeAssistantDiscovery</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="grid">
|
||||
<label for="mqtt-server">
|
||||
<label>
|
||||
<span data-i18n>settings.mqtt.server</span>
|
||||
<input type="text" id="mqtt-server" name="mqtt[server]" maxlength="80" required>
|
||||
<input type="text" name="mqtt[server]" maxlength="80" required>
|
||||
</label>
|
||||
|
||||
<label for="mqtt-port">
|
||||
<label>
|
||||
<span data-i18n>settings.mqtt.port</span>
|
||||
<input type="number" inputmode="numeric" id="mqtt-port" name="mqtt[port]" min="1" max="65535" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="mqtt[port]" min="1" max="65535" step="1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<label for="mqtt-user">
|
||||
<label>
|
||||
<span data-i18n>settings.mqtt.user</span>
|
||||
<input type="text" id="mqtt-user" name="mqtt[user]" maxlength="32" required>
|
||||
<input type="text" name="mqtt[user]" maxlength="32" required>
|
||||
</label>
|
||||
|
||||
<label for="mqtt-password">
|
||||
<label>
|
||||
<span data-i18n>settings.mqtt.password</span>
|
||||
<input type="password" id="mqtt-password" name="mqtt[password]" maxlength="32">
|
||||
<input type="password" name="mqtt[password]" maxlength="32">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<label for="mqtt-prefix">
|
||||
<label>
|
||||
<span data-i18n>settings.mqtt.prefix</span>
|
||||
<input type="text" id="mqtt-prefix" name="mqtt[prefix]" maxlength="32" required>
|
||||
<input type="text" name="mqtt[prefix]" maxlength="32" required>
|
||||
</label>
|
||||
|
||||
<label for="mqtt-interval">
|
||||
<label>
|
||||
<span data-i18n>settings.mqtt.interval</span>
|
||||
<input type="number" inputmode="numeric" id="mqtt-interval" name="mqtt[interval]" min="3" max="60" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="mqtt[interval]" min="3" max="60" step="1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -530,33 +545,33 @@
|
||||
<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">
|
||||
<label>
|
||||
<input type="checkbox" name="externalPump[use]" value="true">
|
||||
<span data-i18n>settings.extPump.use</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="grid">
|
||||
<label for="extpump-gpio">
|
||||
<label>
|
||||
<span data-i18n>settings.extPump.gpio</span>
|
||||
<input type="number" inputmode="numeric" id="extpump-gpio" name="externalPump[gpio]" min="0" max="254" step="1">
|
||||
<input type="number" inputmode="numeric" name="externalPump[gpio]" min="0" max="254" step="1">
|
||||
</label>
|
||||
|
||||
<label for="extpump-pc-time">
|
||||
<label>
|
||||
<span data-i18n>settings.extPump.postCirculationTime</span>
|
||||
<input type="number" inputmode="numeric" id="extpump-pc-time" name="externalPump[postCirculationTime]" min="1" max="120" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="externalPump[postCirculationTime]" min="1" max="120" step="1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<label for="extpump-as-interval">
|
||||
<label>
|
||||
<span data-i18n>settings.extPump.antiStuckInterval</span>
|
||||
<input type="number" inputmode="numeric" id="extpump-as-interval" name="externalPump[antiStuckInterval]" min="1" max="366" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="externalPump[antiStuckInterval]" min="1" max="366" step="1" required>
|
||||
</label>
|
||||
|
||||
<label for="extpump-as-time">
|
||||
<label>
|
||||
<span data-i18n>settings.extPump.antiStuckTime</span>
|
||||
<input type="number" inputmode="numeric" id="extpump-as-time" name="externalPump[antiStuckTime]" min="1" max="20" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="externalPump[antiStuckTime]" min="1" max="20" step="1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -573,74 +588,74 @@
|
||||
<div id="cc-settings-busy" aria-busy="true"></div>
|
||||
<form action="/api/settings" id="cc-settings" class="hidden">
|
||||
<fieldset>
|
||||
<label for="cc-input-enable">
|
||||
<input type="checkbox" id="cc-input-enable" name="cascadeControl[input][enabled]" value="true">
|
||||
<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 for="cc-input-invert-state">
|
||||
<input type="checkbox" id="cc-input-invert-state" name="cascadeControl[input][invertState]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="cascadeControl[input][invertState]" value="true">
|
||||
<span data-i18n>settings.cascadeControl.input.invertState</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="grid">
|
||||
<label for="cc-input-gpio">
|
||||
<label>
|
||||
<span data-i18n>settings.cascadeControl.input.gpio</span>
|
||||
<input type="number" inputmode="numeric" id="cc-input-gpio" name="cascadeControl[input][gpio]" min="0" max="254" step="1">
|
||||
<input type="number" inputmode="numeric" name="cascadeControl[input][gpio]" min="0" max="254" step="1">
|
||||
</label>
|
||||
|
||||
<label for="cc-input-tt">
|
||||
<label>
|
||||
<span data-i18n>settings.cascadeControl.input.thresholdTime</span>
|
||||
<input type="number" inputmode="numeric" id="cc-input-tt" name="cascadeControl[input][thresholdTime]" min="5" max="600" step="1" required>
|
||||
<input type="number" inputmode="numeric" name="cascadeControl[input][thresholdTime]" min="5" max="600" step="1" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<fieldset>
|
||||
<label for="cc-output-enable">
|
||||
<input type="checkbox" id="cc-output-enable" name="cascadeControl[output][enabled]" value="true">
|
||||
<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 for="cc-output-invert-state">
|
||||
<input type="checkbox" id="cc-output-invert-state" name="cascadeControl[output][invertState]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="cascadeControl[output][invertState]" value="true">
|
||||
<span data-i18n>settings.cascadeControl.output.invertState</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="grid">
|
||||
<label for="cc-output-gpio">
|
||||
<label>
|
||||
<span data-i18n>settings.cascadeControl.output.gpio</span>
|
||||
<input type="number" outputmode="numeric" id="cc-output-gpio" name="cascadeControl[output][gpio]" min="0" max="254" step="1">
|
||||
<input type="number" outputmode="numeric" name="cascadeControl[output][gpio]" min="0" max="254" step="1">
|
||||
</label>
|
||||
|
||||
<label for="cc-output-tt">
|
||||
<label>
|
||||
<span data-i18n>settings.cascadeControl.output.thresholdTime</span>
|
||||
<input type="number" outputmode="numeric" id="cc-output-tt" name="cascadeControl[output][thresholdTime]" min="5" max="600" step="1" required>
|
||||
<input type="number" outputmode="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 for="cc-on-fault">
|
||||
<input type="checkbox" id="cc-on-fault" name="cascadeControl[output][onFault]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="cascadeControl[output][onFault]" value="true">
|
||||
<span data-i18n>settings.cascadeControl.output.events.onFault</span>
|
||||
</label>
|
||||
|
||||
<label for="cc-on-loss-conn">
|
||||
<input type="checkbox" id="cc-on-loss-conn" name="cascadeControl[output][onLossConnection]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="cascadeControl[output][onLossConnection]" value="true">
|
||||
<span data-i18n>settings.cascadeControl.output.events.onLossConnection</span>
|
||||
</label>
|
||||
|
||||
<label for="cc-on-enabled-heating">
|
||||
<input type="checkbox" id="cc-on-enabled-heating" name="cascadeControl[output][onEnabledHeating]" value="true">
|
||||
<label>
|
||||
<input type="checkbox" name="cascadeControl[output][onEnabledHeating]" value="true">
|
||||
<span data-i18n>settings.cascadeControl.output.events.onEnabledHeating</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
@@ -671,111 +686,114 @@
|
||||
|
||||
const fillData = (data) => {
|
||||
// System
|
||||
setSelectValue('#system-log-level', data.system.logLevel);
|
||||
setCheckboxValue('#system-serial-enable', data.system.serial.enabled);
|
||||
setSelectValue('#system-serial-baudrate', data.system.serial.baudrate);
|
||||
setCheckboxValue('#system-telnet-enable', data.system.telnet.enabled);
|
||||
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 : '');
|
||||
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);
|
||||
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('#portal-auth', data.portal.auth);
|
||||
setInputValue('#portal-login', data.portal.login);
|
||||
setInputValue('#portal-password', data.portal.password);
|
||||
setCheckboxValue("[name='portal[auth]']", data.portal.auth);
|
||||
setInputValue("[name='portal[login]']", data.portal.login);
|
||||
setInputValue("[name='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', data.opentherm.memberId);
|
||||
setInputValue('#opentherm-flags', data.opentherm.flags);
|
||||
setInputValue('#opentherm-max-modulation', data.opentherm.maxModulation);
|
||||
setInputValue('#opentherm-min-power', data.opentherm.minPower);
|
||||
setInputValue('#opentherm-max-power', data.opentherm.maxPower);
|
||||
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);
|
||||
setCheckboxValue('#opentherm-native-heating-control', data.opentherm.nativeHeatingControl);
|
||||
setCheckboxValue('#opentherm-immergas-fix', data.opentherm.immergasFix);
|
||||
setBusy('#opentherm-settings-busy', '#opentherm-settings', false);
|
||||
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[maxModulation]']", data.opentherm.maxModulation);
|
||||
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][modulationSyncWithHeating]']", data.opentherm.options.modulationSyncWithHeating);
|
||||
setCheckboxValue("[name='opentherm[options][maxTempSyncWithTargetTemp]']", data.opentherm.options.maxTempSyncWithTargetTemp);
|
||||
setCheckboxValue("[name='opentherm[options][getMinMaxTemp]']", data.opentherm.options.getMinMaxTemp);
|
||||
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('#mqtt-enable', data.mqtt.enabled);
|
||||
setCheckboxValue('#mqtt-ha-discovery', data.mqtt.homeAssistantDiscovery);
|
||||
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);
|
||||
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('#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);
|
||||
setCheckboxValue("[name='externalPump[use]']", data.externalPump.use);
|
||||
setInputValue("[name='externalPump[gpio]']", data.externalPump.gpio < 255 ? data.externalPump.gpio : '');
|
||||
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('#cc-input-enable', data.cascadeControl.input.enabled);
|
||||
setInputValue('#cc-input-gpio', data.cascadeControl.input.gpio < 255 ? data.cascadeControl.input.gpio : '');
|
||||
setCheckboxValue('#cc-input-invert-state', data.cascadeControl.input.invertState);
|
||||
setInputValue('#cc-input-tt', data.cascadeControl.input.thresholdTime);
|
||||
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('#cc-output-enable', data.cascadeControl.output.enabled);
|
||||
setInputValue('#cc-output-gpio', data.cascadeControl.output.gpio < 255 ? data.cascadeControl.output.gpio : '');
|
||||
setCheckboxValue('#cc-output-invert-state', data.cascadeControl.output.invertState);
|
||||
setInputValue('#cc-output-tt', data.cascadeControl.output.thresholdTime);
|
||||
setCheckboxValue('#cc-on-fault', data.cascadeControl.output.onFault);
|
||||
setCheckboxValue('#cc-on-loss-conn', data.cascadeControl.output.onLossConnection);
|
||||
setCheckboxValue('#cc-on-enabled-heating', data.cascadeControl.output.onEnabledHeating);
|
||||
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('#heating-min-temp', data.heating.minTemp, {
|
||||
setInputValue("[name='heating[minTemp]']", data.heating.minTemp, {
|
||||
"min": data.system.unitSystem == 0 ? 0 : 32,
|
||||
"max": data.system.unitSystem == 0 ? 99 : 211
|
||||
});
|
||||
setInputValue('#heating-max-temp', data.heating.maxTemp, {
|
||||
setInputValue("[name='heating[maxTemp]']", 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-turbo-factor', data.heating.turboFactor);
|
||||
setInputValue("[name='heating[hysteresis]']", data.heating.hysteresis);
|
||||
setInputValue("[name='heating[turboFactor]']", data.heating.turboFactor);
|
||||
setBusy('#heating-settings-busy', '#heating-settings', false);
|
||||
|
||||
// DHW
|
||||
setInputValue('#dhw-min-temp', data.dhw.minTemp, {
|
||||
setInputValue("[name='dhw[minTemp]']", data.dhw.minTemp, {
|
||||
"min": data.system.unitSystem == 0 ? 0 : 32,
|
||||
"max": data.system.unitSystem == 0 ? 99 : 211
|
||||
});
|
||||
setInputValue('#dhw-max-temp', data.dhw.maxTemp, {
|
||||
setInputValue("[name='dhw[maxTemp]']", 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
|
||||
setInputValue('#emergency-treshold-time', data.emergency.tresholdTime);
|
||||
if (data.opentherm.nativeHeatingControl) {
|
||||
setInputValue('#emergency-target', data.emergency.target, {
|
||||
setInputValue("[name='emergency[tresholdTime]']", data.emergency.tresholdTime);
|
||||
if (data.opentherm.options.nativeHeatingControl) {
|
||||
setInputValue("[name='emergency[target]']", data.emergency.target, {
|
||||
"min": data.system.unitSystem == 0 ? 5 : 41,
|
||||
"max": data.system.unitSystem == 0 ? 30 : 86
|
||||
});
|
||||
|
||||
} else {
|
||||
setInputValue('#emergency-target', data.emergency.target, {
|
||||
setInputValue("[name='emergency[target]']", data.emergency.target, {
|
||||
"min": data.heating.minTemp,
|
||||
"max": data.heating.maxTemp,
|
||||
});
|
||||
@@ -784,23 +802,23 @@
|
||||
setBusy('#emergency-settings-busy', '#emergency-settings', false);
|
||||
|
||||
// Equitherm
|
||||
setCheckboxValue('#equitherm-enable', data.equitherm.enabled);
|
||||
setInputValue('#equitherm-n-factor', data.equitherm.n_factor);
|
||||
setInputValue('#equitherm-k-factor', data.equitherm.k_factor);
|
||||
setInputValue('#equitherm-t-factor', data.equitherm.t_factor);
|
||||
setCheckboxValue("[name='equitherm[enabled]']", data.equitherm.enabled);
|
||||
setInputValue("[name='equitherm[n_factor]']", data.equitherm.n_factor);
|
||||
setInputValue("[name='equitherm[k_factor]']", data.equitherm.k_factor);
|
||||
setInputValue("[name='equitherm[t_factor]']", data.equitherm.t_factor);
|
||||
setBusy('#equitherm-settings-busy', '#equitherm-settings', false);
|
||||
|
||||
// PID
|
||||
setCheckboxValue('#pid-enable', data.pid.enabled);
|
||||
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, {
|
||||
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('#pid-max-temp', data.pid.maxTemp, {
|
||||
setInputValue("[name='pid[maxTemp]']", data.pid.maxTemp, {
|
||||
"min": (data.system.unitSystem == 0 ? 0 : 33),
|
||||
"max": (data.system.unitSystem == 0 ? 100 : 212)
|
||||
});
|
||||
@@ -827,7 +845,7 @@
|
||||
setupForm('#emergency-settings', fillData);
|
||||
setupForm('#equitherm-settings', fillData);
|
||||
setupForm('#pid-settings', fillData);
|
||||
setupForm('#opentherm-settings', fillData);
|
||||
setupForm('#ot-settings', fillData);
|
||||
setupForm('#mqtt-settings', fillData, ['mqtt.user', 'mqtt.password', 'mqtt.prefix']);
|
||||
setupForm('#extpump-settings', fillData);
|
||||
setupForm('#cc-settings', fillData);
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<input type="file" name="settings" id="restore-file" accept=".json">
|
||||
</label>
|
||||
|
||||
<div class="grid">
|
||||
<div role="group">
|
||||
<button type="submit" data-i18n>button.restore</button>
|
||||
<button type="button" class="secondary" onclick="window.location='/api/backup/save';" data-i18n>button.backup</button>
|
||||
</div>
|
||||
|
||||
@@ -115,6 +115,7 @@ tr.network:hover {
|
||||
font-family: var(--pico-font-family-monospace);
|
||||
}
|
||||
|
||||
|
||||
.thermostat {
|
||||
display: grid;
|
||||
grid-template-columns: 0.5fr 2fr 0.5fr;
|
||||
@@ -193,6 +194,92 @@ tr.network:hover {
|
||||
margin: 1.25rem 0;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 575px) {
|
||||
.notify {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 0.5fr;
|
||||
gap: 0.5rem 0.5rem;
|
||||
grid-template-areas:
|
||||
"notify-content"
|
||||
"notify-actions";
|
||||
}
|
||||
|
||||
.notify-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.notify-content {
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
grid-area: notify-content;
|
||||
}
|
||||
|
||||
.notify-actions {
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
grid-area: notify-actions;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 576px) {
|
||||
.notify {
|
||||
display: grid;
|
||||
grid-template-columns: 5rem 1fr 10rem;
|
||||
grid-template-rows: 1fr;
|
||||
gap: 0rem 0.5rem;
|
||||
grid-auto-flow: row;
|
||||
grid-template-areas:
|
||||
"notify-icon notify-content notify-actions";
|
||||
}
|
||||
|
||||
.notify-icon {
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
grid-area: notify-icon;
|
||||
}
|
||||
|
||||
.notify-content {
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
grid-area: notify-content;
|
||||
}
|
||||
|
||||
.notify-actions {
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
grid-area: notify-actions;
|
||||
}
|
||||
}
|
||||
|
||||
.notify {
|
||||
margin: 1rem;
|
||||
padding: 0.5rem;
|
||||
border: .25rem solid var(--pico-blockquote-border-color);
|
||||
}
|
||||
|
||||
.notify-error {
|
||||
border-color: var(--pico-form-element-invalid-border-color);
|
||||
}
|
||||
|
||||
.notify-error .notify-icon {
|
||||
color: var(--pico-form-element-invalid-border-color);
|
||||
}
|
||||
|
||||
.notify-alarm {
|
||||
border-color: #c89048;
|
||||
}
|
||||
|
||||
.notify-alarm .notify-icon {
|
||||
color: #c89048;
|
||||
}
|
||||
|
||||
.notify-icon i {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
|
||||
[class*=" icons-"],
|
||||
[class=icons],
|
||||
[class^=icons-] {
|
||||
|
||||