Compare commits
29 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 | ||
|
|
7efcbaa57e |
64
README.md
@@ -1,40 +1,44 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||

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

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- Hot water temperature control
|
- DHW temperature control
|
||||||
- Heating temperature control
|
- Heating temperature control
|
||||||
- Smart heating temperature control modes:
|
- Smart heating temperature control modes:
|
||||||
- PID
|
- PID
|
||||||
- Equithermic curves - adjusts the temperature based on indoor and outdoor temperatures
|
- Equithermic curves - adjusts the temperature based on indoor and outdoor temperatures
|
||||||
- Hysteresis setting (for accurate maintenance of room temperature)
|
- 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))
|
- 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. 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).
|
- Emergency mode. In any dangerous situation _(loss of connection with Wifi, MQTT, sensors, etc)_ it will not let you and your home freeze.
|
||||||
- Automatic error reset (not with all boilers)
|
- Ability of remote fault reset _(not with all boilers)_
|
||||||
- Diagnostics:
|
- Diagnostics:
|
||||||
- The process of heating: works/does not work
|
- Displaying gateway status
|
||||||
- The process of heating water for hot water: working/not working
|
- Displaying the connection status to the boiler via OpenTherm
|
||||||
- Display of boiler errors
|
- Displaying the fault status and fault code
|
||||||
- Burner status (flame): on/off
|
- Displaying the diagnostic status & diagnostic code
|
||||||
- Burner modulation level in percent
|
- Display of the process of heating: works/does not work
|
||||||
- Pressure in the heating system
|
- Display of burner (flame) status: on/off
|
||||||
- Gateway status (depending on errors and connection status)
|
- Display of burner modulation level in percent
|
||||||
- Boiler connection status via OpenTherm interface
|
- Display of pressure in the heating system
|
||||||
- The current temperature of the heat carrier (usually the return heat carrier)
|
- Display of current temperature of the heat carrier
|
||||||
- Set heat carrier temperature (depending on the selected mode)
|
- Display of return temperature of the heat carrier
|
||||||
- Current hot water temperature
|
- 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!
|
- [Home Assistant](https://www.home-assistant.io/) integration via MQTT. The ability to create any automation for the boiler!
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
All available information and instructions can be found in the wiki:
|
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)
|
* [Ratios](https://github.com/Laxilef/OTGateway/wiki#ratios)
|
||||||
* [Fit coefficients](https://github.com/Laxilef/OTGateway/wiki#fit-coefficients)
|
* [Fit coefficients](https://github.com/Laxilef/OTGateway/wiki#fit-coefficients)
|
||||||
* [PID mode](https://github.com/Laxilef/OTGateway/wiki#pid-mode)
|
* [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)
|
* [Compatibility](https://github.com/Laxilef/OTGateway/wiki/Compatibility)
|
||||||
* [Boilers](https://github.com/Laxilef/OTGateway/wiki/Compatibility#boilers)
|
* [Boilers](https://github.com/Laxilef/OTGateway/wiki/Compatibility#boilers)
|
||||||
* [Boards](https://github.com/Laxilef/OTGateway/wiki/Compatibility#boards)
|
* [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)
|
* [Connection](https://github.com/Laxilef/OTGateway/wiki/OT-adapters#connection)
|
||||||
* [Leds on board](https://github.com/Laxilef/OTGateway/wiki/OT-adapters#leds-on-board)
|
* [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.
|
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
22699
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>
|
template <class T>
|
||||||
void send(int code, T contentType, const JsonVariantConst content, bool pretty = false) {
|
void send(int code, T contentType, const JsonVariantConst content, bool pretty = false) {
|
||||||
|
auto contentLength = pretty ? measureJsonPretty(content) : measureJson(content);
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
if (!this->webServer->chunkedResponseModeStart(code, contentType)) {
|
if (!this->webServer->chunkedResponseModeStart(code, contentType)) {
|
||||||
this->webServer->send(505, F("text/html"), F("HTTP1.1 required"));
|
this->webServer->send(505, F("text/html"), F("HTTP1.1 required"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->webServer->setContentLength(measureJson(content));
|
this->webServer->setContentLength(contentLength);
|
||||||
#else
|
#else
|
||||||
this->webServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
|
this->webServer->setContentLength(contentLength);
|
||||||
this->webServer->sendHeader(F("Content-Length"), String(measureJson(content)));
|
|
||||||
this->webServer->send(code, contentType, emptyString);
|
this->webServer->send(code, contentType, emptyString);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,17 @@
|
|||||||
|
|
||||||
class CustomOpenTherm : public OpenTherm {
|
class CustomOpenTherm : public OpenTherm {
|
||||||
public:
|
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, byte)> BeforeSendRequestCallback;
|
||||||
typedef std::function<void(unsigned long, unsigned long, OpenThermResponseStatus, byte)> AfterSendRequestCallback;
|
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() {}
|
||||||
|
|
||||||
CustomOpenTherm* setYieldCallback(YieldCallback callback = nullptr) {
|
CustomOpenTherm* setDelayCallback(DelayCallback callback = nullptr) {
|
||||||
this->yieldCallback = callback;
|
this->delayCallback = callback;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -28,14 +30,28 @@ public:
|
|||||||
return this;
|
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) {
|
unsigned long sendRequest(unsigned long request, byte attempts = 5, byte _attempt = 0) {
|
||||||
_attempt++;
|
_attempt++;
|
||||||
|
|
||||||
while (!this->isReady()) {
|
while (!this->isReady()) {
|
||||||
if (this->yieldCallback) {
|
if (this->delayCallback) {
|
||||||
this->yieldCallback();
|
this->delayCallback(150);
|
||||||
} else {
|
|
||||||
::yield();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->process();
|
this->process();
|
||||||
@@ -51,17 +67,13 @@ public:
|
|||||||
_response = 0;
|
_response = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
while (true) {
|
do {
|
||||||
this->process();
|
if (this->delayCallback) {
|
||||||
|
this->delayCallback(150);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->status == OpenThermStatus::READY || this->status == OpenThermStatus::DELAY) {
|
this->process();
|
||||||
break;
|
} while (this->status != OpenThermStatus::READY && this->status != OpenThermStatus::DELAY);
|
||||||
} else if (this->yieldCallback) {
|
|
||||||
this->yieldCallback();
|
|
||||||
} else {
|
|
||||||
::yield();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_response = this->getLastResponse();
|
_response = this->getLastResponse();
|
||||||
_responseStatus = this->getLastResponseStatus();
|
_responseStatus = this->getLastResponseStatus();
|
||||||
@@ -151,7 +163,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
YieldCallback yieldCallback;
|
DelayCallback delayCallback;
|
||||||
BeforeSendRequestCallback beforeSendRequestCallback;
|
BeforeSendRequestCallback beforeSendRequestCallback;
|
||||||
AfterSendRequestCallback afterSendRequestCallback;
|
AfterSendRequestCallback afterSendRequestCallback;
|
||||||
|
int _outPin;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ extra_configs = secrets.default.ini
|
|||||||
core_dir = .pio
|
core_dir = .pio
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
version = 1.5.0
|
version = 1.5.1
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
bblanchon/ArduinoJson@^7.1.0
|
bblanchon/ArduinoJson@^7.3.0
|
||||||
;ihormelnyk/OpenTherm Library@^1.1.5
|
;ihormelnyk/OpenTherm Library@^1.1.5
|
||||||
https://github.com/ihormelnyk/opentherm_library#master
|
https://github.com/ihormelnyk/opentherm_library#master
|
||||||
;arduino-libraries/ArduinoMqttClient@^0.1.8
|
;arduino-libraries/ArduinoMqttClient@^0.1.8
|
||||||
@@ -85,13 +85,13 @@ board_build.ldscript = eagle.flash.4m1m.ld
|
|||||||
;platform_packages =
|
;platform_packages =
|
||||||
; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.5
|
; 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
|
; 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 =
|
platform_packages =
|
||||||
board_build.partitions = esp32_partitions.csv
|
board_build.partitions = esp32_partitions.csv
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
laxilef/ESP32Scheduler@^1.0.1
|
laxilef/ESP32Scheduler@^1.0.1
|
||||||
nimble_lib = h2zero/NimBLE-Arduino@^1.4.2
|
nimble_lib = h2zero/NimBLE-Arduino@^2.1.0
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
post:tools/esp32.py
|
post:tools/esp32.py
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ public:
|
|||||||
if (sSensor.type == Sensors::Type::BLUETOOTH) {
|
if (sSensor.type == Sensors::Type::BLUETOOTH) {
|
||||||
// available state topic
|
// available state topic
|
||||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = doc[FPSTR(HA_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;
|
String sName = sSensor.name;
|
||||||
switch (vType) {
|
switch (vType) {
|
||||||
@@ -254,7 +254,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
// available state topic
|
// available state topic
|
||||||
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = doc[FPSTR(HA_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_NAME)] = sSensor.name;
|
||||||
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.value|float(0)|round(2) }}");
|
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.value|float(0)|round(2) }}");
|
||||||
@@ -970,7 +970,7 @@ public:
|
|||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
|
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_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_AVAILABILITY_MODE)] = F("all");
|
||||||
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating"));
|
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating"));
|
||||||
@@ -991,7 +991,7 @@ public:
|
|||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
|
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_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_AVAILABILITY_MODE)] = F("all");
|
||||||
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw"));
|
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw"));
|
||||||
@@ -1012,7 +1012,7 @@ public:
|
|||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
|
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_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_AVAILABILITY_MODE)] = F("all");
|
||||||
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("flame"));
|
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("flame"));
|
||||||
@@ -1033,7 +1033,7 @@ public:
|
|||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
|
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_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_AVAILABILITY_MODE)] = F("all");
|
||||||
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("fault"));
|
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("fault"));
|
||||||
@@ -1054,7 +1054,7 @@ public:
|
|||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
|
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_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_AVAILABILITY_MODE)] = F("all");
|
||||||
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||||
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC));
|
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC));
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ protected:
|
|||||||
emergencyFlags |= 0b00000010;
|
emergencyFlags |= 0b00000010;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.opentherm.nativeHeatingControl) {
|
if (settings.opentherm.options.nativeHeatingControl) {
|
||||||
emergencyFlags |= 0b00000100;
|
emergencyFlags |= 0b00000100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -532,13 +532,13 @@ protected:
|
|||||||
|
|
||||||
bool publishNonStaticHaEntities(bool force = false) {
|
bool publishNonStaticHaEntities(bool force = false) {
|
||||||
static byte _heatingMinTemp, _heatingMaxTemp, _dhwMinTemp, _dhwMaxTemp = 0;
|
static byte _heatingMinTemp, _heatingMaxTemp, _dhwMinTemp, _dhwMaxTemp = 0;
|
||||||
static bool _indoorTempControl, _dhwPresent = false;
|
static bool _indoorTempControl, _dhwSupport = false;
|
||||||
|
|
||||||
bool published = false;
|
bool published = false;
|
||||||
if (force || _dhwPresent != settings.opentherm.dhwPresent) {
|
if (force || _dhwSupport != settings.opentherm.options.dhwSupport) {
|
||||||
_dhwPresent = settings.opentherm.dhwPresent;
|
_dhwSupport = settings.opentherm.options.dhwSupport;
|
||||||
|
|
||||||
if (_dhwPresent) {
|
if (_dhwSupport) {
|
||||||
this->haHelper->publishInputDhwMinTemp(settings.system.unitSystem);
|
this->haHelper->publishInputDhwMinTemp(settings.system.unitSystem);
|
||||||
this->haHelper->publishInputDhwMaxTemp(settings.system.unitSystem);
|
this->haHelper->publishInputDhwMaxTemp(settings.system.unitSystem);
|
||||||
this->haHelper->publishDhwState();
|
this->haHelper->publishDhwState();
|
||||||
@@ -569,7 +569,7 @@ protected:
|
|||||||
published = true;
|
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;
|
_dhwMinTemp = settings.dhw.minTemp;
|
||||||
_dhwMaxTemp = settings.dhw.maxTemp;
|
_dhwMaxTemp = settings.dhw.maxTemp;
|
||||||
|
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ protected:
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this->instance->setYieldCallback([this]() {
|
this->instance->setDelayCallback([this](unsigned int time) {
|
||||||
this->delay(25);
|
this->delay(time);
|
||||||
});
|
});
|
||||||
|
|
||||||
this->instance->begin();
|
this->instance->begin();
|
||||||
@@ -153,18 +153,18 @@ protected:
|
|||||||
&& !vars.master.heating.blocking;
|
&& !vars.master.heating.blocking;
|
||||||
|
|
||||||
// DHW settings
|
// 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;
|
vars.master.dhw.targetTemp = settings.dhw.target;
|
||||||
|
|
||||||
// CH2 settings
|
// CH2 settings
|
||||||
vars.master.ch2.enabled = settings.opentherm.heatingCh2Enabled
|
vars.master.ch2.enabled = settings.opentherm.options.ch2AlwaysEnabled
|
||||||
|| (settings.opentherm.heatingCh1ToCh2 && vars.master.heating.enabled)
|
|| (settings.opentherm.options.heatingToCh2 && vars.master.heating.enabled)
|
||||||
|| (settings.opentherm.dhwToCh2 && settings.opentherm.dhwPresent && settings.dhw.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;
|
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;
|
vars.master.ch2.targetTemp = vars.master.dhw.targetTemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,18 +174,24 @@ protected:
|
|||||||
|
|
||||||
// Immergas fix
|
// Immergas fix
|
||||||
// https://arduino.ru/forum/programmirovanie/termostat-opentherm-na-esp8266?page=15#comment-649392
|
// https://arduino.ru/forum/programmirovanie/termostat-opentherm-na-esp8266?page=15#comment-649392
|
||||||
if (settings.opentherm.immergasFix) {
|
if (settings.opentherm.options.immergasFix) {
|
||||||
statusLb = 0xCA;
|
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(
|
unsigned long response = this->instance->setBoilerStatus(
|
||||||
vars.master.heating.enabled,
|
vars.master.heating.enabled,
|
||||||
vars.master.dhw.enabled,
|
vars.master.dhw.enabled,
|
||||||
false,
|
settings.opentherm.options.coolingSupport,
|
||||||
settings.opentherm.nativeHeatingControl,
|
settings.opentherm.options.nativeHeatingControl,
|
||||||
vars.master.ch2.enabled,
|
vars.master.ch2.enabled,
|
||||||
settings.opentherm.summerWinterMode,
|
summerWinterMode,
|
||||||
settings.opentherm.dhwBlocking,
|
settings.opentherm.options.dhwBlocking,
|
||||||
statusLb
|
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"));
|
Log.sinfoln(FPSTR(L_OT), F("Connected"));
|
||||||
|
|
||||||
vars.slave.connected = true;
|
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"));
|
Log.swarningln(FPSTR(L_OT), F("Disconnected"));
|
||||||
|
|
||||||
// Mark sensors as disconnected
|
// Mark sensors as disconnected
|
||||||
@@ -242,6 +248,8 @@ protected:
|
|||||||
vars.slave.diag.active = false;
|
vars.slave.diag.active = false;
|
||||||
vars.slave.diag.code = 0;
|
vars.slave.diag.code = 0;
|
||||||
|
|
||||||
|
this->instance->reset();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,15 +273,16 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
vars.slave.heating.active = CustomOpenTherm::isCentralHeatingActive(response);
|
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.flame = CustomOpenTherm::isFlameOn(response);
|
||||||
|
vars.slave.cooling = CustomOpenTherm::isCoolingActive(response);
|
||||||
vars.slave.fault.active = CustomOpenTherm::isFault(response);
|
vars.slave.fault.active = CustomOpenTherm::isFault(response);
|
||||||
vars.slave.diag.active = CustomOpenTherm::isDiagnostic(response);
|
vars.slave.diag.active = CustomOpenTherm::isDiagnostic(response);
|
||||||
|
|
||||||
Log.snoticeln(
|
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.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
|
// 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"));
|
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)) {
|
if (this->setMaxModulationLevel(0)) {
|
||||||
Log.snoticeln(FPSTR(L_OT), F("Set max modulation: 0% (response: %hhu%%)"), vars.slave.modulation.max);
|
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)
|
// 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()) {
|
if (this->updateMinMaxDhwTemp()) {
|
||||||
uint8_t convertedMinTemp = convertTemp(
|
uint8_t convertedMinTemp = convertTemp(
|
||||||
vars.slave.dhw.minTemp,
|
vars.slave.dhw.minTemp,
|
||||||
@@ -380,7 +389,7 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
// Get heating min/max temp
|
// Get heating min/max temp
|
||||||
if (settings.opentherm.getMinMaxTemp) {
|
if (settings.opentherm.options.getMinMaxTemp) {
|
||||||
if (this->updateMinMaxHeatingTemp()) {
|
if (this->updateMinMaxHeatingTemp()) {
|
||||||
uint8_t convertedMinTemp = convertTemp(
|
uint8_t convertedMinTemp = convertTemp(
|
||||||
vars.slave.heating.minTemp,
|
vars.slave.heating.minTemp,
|
||||||
@@ -520,7 +529,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update DHW temp
|
// 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();
|
bool result = this->updateDhwTemp();
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
@@ -546,7 +555,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update DHW temp 2
|
// 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()) {
|
if (this->updateDhwTemp2()) {
|
||||||
float convertedDhwTemp2 = convertTemp(
|
float convertedDhwTemp2 = convertTemp(
|
||||||
vars.slave.dhw.currentTemp2,
|
vars.slave.dhw.currentTemp2,
|
||||||
@@ -570,7 +579,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update DHW flow rate
|
// 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()) {
|
if (this->updateDhwFlowRate()) {
|
||||||
float convertedDhwFlowRate = convertVolume(
|
float convertedDhwFlowRate = convertVolume(
|
||||||
vars.slave.dhw.flowRate,
|
vars.slave.dhw.flowRate,
|
||||||
@@ -643,7 +652,7 @@ protected:
|
|||||||
|
|
||||||
// Update CH2 temp
|
// Update CH2 temp
|
||||||
if (Sensors::getAmountByType(Sensors::Type::OT_CH2_TEMP, true)) {
|
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()) {
|
if (this->updateCh2Temp()) {
|
||||||
float convertedCh2Temp = convertTemp(
|
float convertedCh2Temp = convertTemp(
|
||||||
vars.slave.ch2.currentTemp,
|
vars.slave.ch2.currentTemp,
|
||||||
@@ -942,7 +951,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Native heating control
|
// Native heating control
|
||||||
if (settings.opentherm.nativeHeatingControl) {
|
if (settings.opentherm.options.nativeHeatingControl) {
|
||||||
// Converted current indoor temp
|
// Converted current indoor temp
|
||||||
float convertedTemp = convertTemp(vars.master.heating.indoorTemp, settings.system.unitSystem, settings.opentherm.unitSystem);
|
float convertedTemp = convertTemp(vars.master.heating.indoorTemp, settings.system.unitSystem, settings.opentherm.unitSystem);
|
||||||
|
|
||||||
@@ -958,7 +967,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set current CH2 indoor temp
|
// Set current CH2 indoor temp
|
||||||
if (settings.opentherm.heatingCh1ToCh2) {
|
if (settings.opentherm.options.heatingToCh2) {
|
||||||
if (this->setRoomTempCh2(convertedTemp)) {
|
if (this->setRoomTempCh2(convertedTemp)) {
|
||||||
Log.sinfoln(
|
Log.sinfoln(
|
||||||
FPSTR(L_OT_HEATING), F("Set current CH2 indoor temp: %.2f (converted: %.2f, response: %.2f)"),
|
FPSTR(L_OT_HEATING), F("Set current CH2 indoor temp: %.2f (converted: %.2f, response: %.2f)"),
|
||||||
@@ -990,7 +999,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set target CH2 temp
|
// Set target CH2 temp
|
||||||
if (settings.opentherm.heatingCh1ToCh2 && this->needSetCh2Temp(convertedTemp)) {
|
if (settings.opentherm.options.heatingToCh2 && this->needSetCh2Temp(convertedTemp)) {
|
||||||
if (this->setRoomSetpointCh2(convertedTemp)) {
|
if (this->setRoomSetpointCh2(convertedTemp)) {
|
||||||
this->ch2SetTempTime = millis();
|
this->ch2SetTempTime = millis();
|
||||||
|
|
||||||
@@ -1006,12 +1015,13 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Normal heating control
|
// Normal heating control
|
||||||
if (!settings.opentherm.nativeHeatingControl && vars.master.heating.enabled) {
|
if (!settings.opentherm.options.nativeHeatingControl && vars.master.heating.enabled) {
|
||||||
// Converted target heating temp
|
// Converted target heating temp
|
||||||
float convertedTemp = convertTemp(vars.master.heating.setpointTemp, settings.system.unitSystem, settings.opentherm.unitSystem);
|
float convertedTemp = convertTemp(vars.master.heating.setpointTemp, settings.system.unitSystem, settings.opentherm.unitSystem);
|
||||||
|
|
||||||
if (this->needSetHeatingTemp(convertedTemp)) {
|
if (this->needSetHeatingTemp(convertedTemp)) {
|
||||||
// Set max heating temp
|
// Set max heating temp
|
||||||
|
if (settings.opentherm.options.maxTempSyncWithTargetTemp) {
|
||||||
if (this->setMaxHeatingTemp(convertedTemp)) {
|
if (this->setMaxHeatingTemp(convertedTemp)) {
|
||||||
Log.sinfoln(
|
Log.sinfoln(
|
||||||
FPSTR(L_OT_HEATING), F("Set max heating temp: %.2f (converted: %.2f)"),
|
FPSTR(L_OT_HEATING), F("Set max heating temp: %.2f (converted: %.2f)"),
|
||||||
@@ -1021,6 +1031,7 @@ protected:
|
|||||||
} else {
|
} else {
|
||||||
Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set max heating temp"));
|
Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set max heating temp"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set target heating temp
|
// Set target heating temp
|
||||||
if (this->setHeatingTemp(convertedTemp)) {
|
if (this->setHeatingTemp(convertedTemp)) {
|
||||||
@@ -1038,8 +1049,8 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set CH2 temp
|
// Set CH2 temp
|
||||||
if (!settings.opentherm.nativeHeatingControl && vars.master.ch2.enabled) {
|
if (!settings.opentherm.options.nativeHeatingControl && vars.master.ch2.enabled) {
|
||||||
if (settings.opentherm.heatingCh1ToCh2 || settings.opentherm.dhwToCh2) {
|
if (settings.opentherm.options.heatingToCh2 || settings.opentherm.options.dhwToCh2) {
|
||||||
// Converted target CH2 temp
|
// Converted target CH2 temp
|
||||||
float convertedTemp = convertTemp(
|
float convertedTemp = convertTemp(
|
||||||
vars.master.ch2.targetTemp,
|
vars.master.ch2.targetTemp,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ protected:
|
|||||||
this->indoorSensorsConnected = Sensors::existsConnectedSensorsByPurpose(Sensors::Purpose::INDOOR_TEMP);
|
this->indoorSensorsConnected = Sensors::existsConnectedSensorsByPurpose(Sensors::Purpose::INDOOR_TEMP);
|
||||||
//this->outdoorSensorsConnected = Sensors::existsConnectedSensorsByPurpose(Sensors::Purpose::OUTDOOR_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.indoorTempControl = true;
|
||||||
vars.master.heating.minTemp = THERMOSTAT_INDOOR_MIN_TEMP;
|
vars.master.heating.minTemp = THERMOSTAT_INDOOR_MIN_TEMP;
|
||||||
vars.master.heating.maxTemp = THERMOSTAT_INDOOR_MAX_TEMP;
|
vars.master.heating.maxTemp = THERMOSTAT_INDOOR_MAX_TEMP;
|
||||||
@@ -93,7 +93,7 @@ protected:
|
|||||||
void hysteresis() {
|
void hysteresis() {
|
||||||
bool useHyst = false;
|
bool useHyst = false;
|
||||||
if (settings.heating.hysteresis > 0.01f && this->indoorSensorsConnected) {
|
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) {
|
if (useHyst) {
|
||||||
@@ -110,13 +110,13 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline float getHeatingMinSetpointTemp() {
|
inline float getHeatingMinSetpointTemp() {
|
||||||
return settings.opentherm.nativeHeatingControl
|
return settings.opentherm.options.nativeHeatingControl
|
||||||
? vars.master.heating.minTemp
|
? vars.master.heating.minTemp
|
||||||
: settings.heating.minTemp;
|
: settings.heating.minTemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float getHeatingMaxSetpointTemp() {
|
inline float getHeatingMaxSetpointTemp() {
|
||||||
return settings.opentherm.nativeHeatingControl
|
return settings.opentherm.options.nativeHeatingControl
|
||||||
? vars.master.heating.maxTemp
|
? vars.master.heating.maxTemp
|
||||||
: settings.heating.maxTemp;
|
: settings.heating.maxTemp;
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ protected:
|
|||||||
if (vars.emergency.state) {
|
if (vars.emergency.state) {
|
||||||
return settings.emergency.target;
|
return settings.emergency.target;
|
||||||
|
|
||||||
} else if (settings.opentherm.nativeHeatingControl) {
|
} else if (settings.opentherm.options.nativeHeatingControl) {
|
||||||
return settings.heating.target;
|
return settings.heating.target;
|
||||||
|
|
||||||
} else if (!settings.equitherm.enabled && !settings.pid.enabled) {
|
} else if (!settings.equitherm.enabled && !settings.pid.enabled) {
|
||||||
|
|||||||
@@ -175,8 +175,12 @@ protected:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (millis() - this->dallasSearchTime[gpio] > this->dallasSearchInterval) {
|
if (millis() - this->dallasSearchTime[gpio] < this->dallasSearchInterval) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
this->dallasSearchTime[gpio] = millis();
|
this->dallasSearchTime[gpio] = millis();
|
||||||
|
this->owInstances[gpio].reset();
|
||||||
instance.begin();
|
instance.begin();
|
||||||
|
|
||||||
Log.straceln(
|
Log.straceln(
|
||||||
@@ -186,7 +190,6 @@ protected:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void fillingAddressesDallasSensors() {
|
void fillingAddressesDallasSensors() {
|
||||||
// check & filling sensors address
|
// check & filling sensors address
|
||||||
@@ -274,26 +277,15 @@ protected:
|
|||||||
unsigned long ts = millis();
|
unsigned long ts = millis();
|
||||||
|
|
||||||
if (this->dallasPolling[gpio]) {
|
if (this->dallasPolling[gpio]) {
|
||||||
auto minPollingTime = instance.millisToWaitForConversion(12);
|
auto minPollingTime = instance.millisToWaitForConversion(12) * 2;
|
||||||
unsigned long estimatePollingTime = ts - this->dallasLastPollingTime[gpio];
|
unsigned long estimatePollingTime = ts - this->dallasLastPollingTime[gpio];
|
||||||
|
|
||||||
// check conversion time
|
// check conversion time
|
||||||
|
// isConversionComplete does not work with chinese clones!
|
||||||
if (estimatePollingTime < minPollingTime) {
|
if (estimatePollingTime < minPollingTime) {
|
||||||
continue;
|
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
|
// read sensors data for current instance
|
||||||
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
||||||
auto& sSensor = Sensors::settings[sensorId];
|
auto& sSensor = Sensors::settings[sensorId];
|
||||||
@@ -345,28 +337,6 @@ protected:
|
|||||||
continue;
|
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
|
// start polling
|
||||||
instance.setResolution(12);
|
instance.setResolution(12);
|
||||||
instance.requestTemperatures();
|
instance.requestTemperatures();
|
||||||
@@ -380,10 +350,10 @@ protected:
|
|||||||
|
|
||||||
void pollingBleSensors() {
|
void pollingBleSensors() {
|
||||||
#if USE_BLE
|
#if USE_BLE
|
||||||
if (!NimBLEDevice::getInitialized() && millis() > 5000) {
|
if (!NimBLEDevice::isInitialized() && millis() > 5000) {
|
||||||
Log.sinfoln(FPSTR(L_SENSORS_BLE), F("Initialized"));
|
Log.sinfoln(FPSTR(L_SENSORS_BLE), F("Initialized"));
|
||||||
BLEDevice::init("");
|
BLEDevice::init("");
|
||||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
NimBLEDevice::setPower(9);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
|
||||||
@@ -445,7 +415,7 @@ protected:
|
|||||||
|
|
||||||
bool connectToBleDevice(const uint8_t sensorId) {
|
bool connectToBleDevice(const uint8_t sensorId) {
|
||||||
#if USE_BLE
|
#if USE_BLE
|
||||||
if (!NimBLEDevice::getInitialized()) {
|
if (!NimBLEDevice::isInitialized()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,7 +430,7 @@ protected:
|
|||||||
sSensor.address[0], sSensor.address[1], sSensor.address[2],
|
sSensor.address[0], sSensor.address[1], sSensor.address[2],
|
||||||
sSensor.address[3], sSensor.address[4], sSensor.address[5]
|
sSensor.address[3], sSensor.address[4], sSensor.address[5]
|
||||||
};
|
};
|
||||||
const NimBLEAddress address = NimBLEAddress(addr);
|
const auto address = NimBLEAddress(addr, 0);
|
||||||
|
|
||||||
NimBLEClient* pClient = nullptr;
|
NimBLEClient* pClient = nullptr;
|
||||||
pClient = NimBLEDevice::getClientByPeerAddress(address);
|
pClient = NimBLEDevice::getClientByPeerAddress(address);
|
||||||
@@ -470,12 +440,13 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pClient == nullptr) {
|
if (pClient == nullptr) {
|
||||||
if (NimBLEDevice::getClientListSize() >= NIMBLE_MAX_CONNECTIONS) {
|
if (NimBLEDevice::getCreatedClientCount() >= NIMBLE_MAX_CONNECTIONS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pClient = NimBLEDevice::createClient();
|
pClient = NimBLEDevice::createClient();
|
||||||
pClient->setConnectTimeout(5);
|
pClient->setConnectTimeout(5000);
|
||||||
|
pClient->setSelfDelete(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pClient->isConnected()) {
|
if(pClient->isConnected()) {
|
||||||
@@ -492,7 +463,6 @@ protected:
|
|||||||
sensorId, sSensor.name, address.toString().c_str()
|
sensorId, sSensor.name, address.toString().c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
NimBLEDevice::deleteClient(pClient);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,7 +506,7 @@ protected:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NimBLERemoteService* pService = pChar->getRemoteService();
|
const NimBLERemoteService* pService = pChar->getRemoteService();
|
||||||
if (pService == nullptr) {
|
if (pService == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -609,7 +579,7 @@ protected:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NimBLERemoteService* pService = pChar->getRemoteService();
|
const NimBLERemoteService* pService = pChar->getRemoteService();
|
||||||
if (pService == nullptr) {
|
if (pService == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -694,7 +664,7 @@ protected:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NimBLERemoteService* pService = pChar->getRemoteService();
|
const NimBLERemoteService* pService = pChar->getRemoteService();
|
||||||
if (pService == nullptr) {
|
if (pService == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -793,7 +763,7 @@ protected:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NimBLERemoteService* pService = pChar->getRemoteService();
|
const NimBLERemoteService* pService = pChar->getRemoteService();
|
||||||
if (pService == nullptr) {
|
if (pService == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,16 +57,21 @@ struct Settings {
|
|||||||
float minPower = 0.0f;
|
float minPower = 0.0f;
|
||||||
float maxPower = 0.0f;
|
float maxPower = 0.0f;
|
||||||
|
|
||||||
bool dhwPresent = true;
|
struct {
|
||||||
|
bool dhwSupport = true;
|
||||||
|
bool coolingSupport = false;
|
||||||
bool summerWinterMode = false;
|
bool summerWinterMode = false;
|
||||||
bool heatingCh2Enabled = true;
|
bool heatingStateToSummerWinterMode = false;
|
||||||
bool heatingCh1ToCh2 = false;
|
bool ch2AlwaysEnabled = true;
|
||||||
|
bool heatingToCh2 = false;
|
||||||
bool dhwToCh2 = false;
|
bool dhwToCh2 = false;
|
||||||
bool dhwBlocking = false;
|
bool dhwBlocking = false;
|
||||||
bool modulationSyncWithHeating = false;
|
bool modulationSyncWithHeating = false;
|
||||||
|
bool maxTempSyncWithTargetTemp = true;
|
||||||
bool getMinMaxTemp = true;
|
bool getMinMaxTemp = true;
|
||||||
bool nativeHeatingControl = false;
|
bool nativeHeatingControl = false;
|
||||||
bool immergasFix = false;
|
bool immergasFix = false;
|
||||||
|
} options;
|
||||||
} opentherm;
|
} opentherm;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -287,6 +292,7 @@ struct Variables {
|
|||||||
|
|
||||||
bool connected = false;
|
bool connected = false;
|
||||||
bool flame = false;
|
bool flame = false;
|
||||||
|
bool cooling = false;
|
||||||
float pressure = 0.0f;
|
float pressure = 0.0f;
|
||||||
float heatExchangerTemp = 0.0f;
|
float heatExchangerTemp = 0.0f;
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,13 @@ const char S_BSSID[] PROGMEM = "bssid";
|
|||||||
const char S_BUILD[] PROGMEM = "build";
|
const char S_BUILD[] PROGMEM = "build";
|
||||||
const char S_CASCADE_CONTROL[] PROGMEM = "cascadeControl";
|
const char S_CASCADE_CONTROL[] PROGMEM = "cascadeControl";
|
||||||
const char S_CHANNEL[] PROGMEM = "channel";
|
const char S_CHANNEL[] PROGMEM = "channel";
|
||||||
|
const char S_CH2_ALWAYS_ENABLED[] PROGMEM = "ch2AlwaysEnabled";
|
||||||
const char S_CHIP[] PROGMEM = "chip";
|
const char S_CHIP[] PROGMEM = "chip";
|
||||||
const char S_CODE[] PROGMEM = "code";
|
const char S_CODE[] PROGMEM = "code";
|
||||||
const char S_CONNECTED[] PROGMEM = "connected";
|
const char S_CONNECTED[] PROGMEM = "connected";
|
||||||
const char S_CONTINUES[] PROGMEM = "continues";
|
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_CORE[] PROGMEM = "core";
|
||||||
const char S_CORES[] PROGMEM = "cores";
|
const char S_CORES[] PROGMEM = "cores";
|
||||||
const char S_CRASH[] PROGMEM = "crash";
|
const char S_CRASH[] PROGMEM = "crash";
|
||||||
@@ -62,7 +65,7 @@ const char S_DATA[] PROGMEM = "data";
|
|||||||
const char S_DATE[] PROGMEM = "date";
|
const char S_DATE[] PROGMEM = "date";
|
||||||
const char S_DHW[] PROGMEM = "dhw";
|
const char S_DHW[] PROGMEM = "dhw";
|
||||||
const char S_DHW_BLOCKING[] PROGMEM = "dhwBlocking";
|
const char S_DHW_BLOCKING[] PROGMEM = "dhwBlocking";
|
||||||
const char S_DHW_PRESENT[] PROGMEM = "dhwPresent";
|
const char S_DHW_SUPPORT[] PROGMEM = "dhwSupport";
|
||||||
const char S_DHW_TO_CH2[] PROGMEM = "dhwToCh2";
|
const char S_DHW_TO_CH2[] PROGMEM = "dhwToCh2";
|
||||||
const char S_DIAG[] PROGMEM = "diag";
|
const char S_DIAG[] PROGMEM = "diag";
|
||||||
const char S_DNS[] PROGMEM = "dns";
|
const char S_DNS[] PROGMEM = "dns";
|
||||||
@@ -88,8 +91,8 @@ const char S_GET_MIN_MAX_TEMP[] PROGMEM = "getMinMaxTemp";
|
|||||||
const char S_GPIO[] PROGMEM = "gpio";
|
const char S_GPIO[] PROGMEM = "gpio";
|
||||||
const char S_HEAP[] PROGMEM = "heap";
|
const char S_HEAP[] PROGMEM = "heap";
|
||||||
const char S_HEATING[] PROGMEM = "heating";
|
const char S_HEATING[] PROGMEM = "heating";
|
||||||
const char S_HEATING_CH1_TO_CH2[] PROGMEM = "heatingCh1ToCh2";
|
const char S_HEATING_TO_CH2[] PROGMEM = "heatingToCh2";
|
||||||
const char S_HEATING_CH2_ENABLED[] PROGMEM = "heatingCh2Enabled";
|
const char S_HEATING_STATE_TO_SUMMER_WINTER_MODE[] PROGMEM = "heatingStateToSummerWinterMode";
|
||||||
const char S_HIDDEN[] PROGMEM = "hidden";
|
const char S_HIDDEN[] PROGMEM = "hidden";
|
||||||
const char S_HOME_ASSISTANT_DISCOVERY[] PROGMEM = "homeAssistantDiscovery";
|
const char S_HOME_ASSISTANT_DISCOVERY[] PROGMEM = "homeAssistantDiscovery";
|
||||||
const char S_HOSTNAME[] PROGMEM = "hostname";
|
const char S_HOSTNAME[] PROGMEM = "hostname";
|
||||||
@@ -115,6 +118,7 @@ const char S_MAX_FREE_BLOCK[] PROGMEM = "maxFreeBlock";
|
|||||||
const char S_MAX_MODULATION[] PROGMEM = "maxModulation";
|
const char S_MAX_MODULATION[] PROGMEM = "maxModulation";
|
||||||
const char S_MAX_POWER[] PROGMEM = "maxPower";
|
const char S_MAX_POWER[] PROGMEM = "maxPower";
|
||||||
const char S_MAX_TEMP[] PROGMEM = "maxTemp";
|
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_MEMBER_ID[] PROGMEM = "memberId";
|
||||||
const char S_MIN[] PROGMEM = "min";
|
const char S_MIN[] PROGMEM = "min";
|
||||||
const char S_MIN_FREE[] PROGMEM = "minFree";
|
const char S_MIN_FREE[] PROGMEM = "minFree";
|
||||||
@@ -134,6 +138,7 @@ const char S_ON_ENABLED_HEATING[] PROGMEM = "onEnabledHeating";
|
|||||||
const char S_ON_FAULT[] PROGMEM = "onFault";
|
const char S_ON_FAULT[] PROGMEM = "onFault";
|
||||||
const char S_ON_LOSS_CONNECTION[] PROGMEM = "onLossConnection";
|
const char S_ON_LOSS_CONNECTION[] PROGMEM = "onLossConnection";
|
||||||
const char S_OPENTHERM[] PROGMEM = "opentherm";
|
const char S_OPENTHERM[] PROGMEM = "opentherm";
|
||||||
|
const char S_OPTIONS[] PROGMEM = "options";
|
||||||
const char S_OUTDOOR_TEMP[] PROGMEM = "outdoorTemp";
|
const char S_OUTDOOR_TEMP[] PROGMEM = "outdoorTemp";
|
||||||
const char S_OUT_GPIO[] PROGMEM = "outGpio";
|
const char S_OUT_GPIO[] PROGMEM = "outGpio";
|
||||||
const char S_OUTPUT[] PROGMEM = "output";
|
const char S_OUTPUT[] PROGMEM = "output";
|
||||||
|
|||||||
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_MAX_MODULATION)] = src.opentherm.maxModulation;
|
||||||
opentherm[FPSTR(S_MIN_POWER)] = roundf(src.opentherm.minPower, 2);
|
opentherm[FPSTR(S_MIN_POWER)] = roundf(src.opentherm.minPower, 2);
|
||||||
opentherm[FPSTR(S_MAX_POWER)] = roundf(src.opentherm.maxPower, 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;
|
auto otOptions = opentherm[FPSTR(S_OPTIONS)].to<JsonObject>();
|
||||||
opentherm[FPSTR(S_HEATING_CH2_ENABLED)] = src.opentherm.heatingCh2Enabled;
|
otOptions[FPSTR(S_DHW_SUPPORT)] = src.opentherm.options.dhwSupport;
|
||||||
opentherm[FPSTR(S_HEATING_CH1_TO_CH2)] = src.opentherm.heatingCh1ToCh2;
|
otOptions[FPSTR(S_COOLING_SUPPORT)] = src.opentherm.options.coolingSupport;
|
||||||
opentherm[FPSTR(S_DHW_TO_CH2)] = src.opentherm.dhwToCh2;
|
otOptions[FPSTR(S_SUMMER_WINTER_MODE)] = src.opentherm.options.summerWinterMode;
|
||||||
opentherm[FPSTR(S_DHW_BLOCKING)] = src.opentherm.dhwBlocking;
|
otOptions[FPSTR(S_HEATING_STATE_TO_SUMMER_WINTER_MODE)] = src.opentherm.options.heatingStateToSummerWinterMode;
|
||||||
opentherm[FPSTR(S_MODULATION_SYNC_WITH_HEATING)] = src.opentherm.modulationSyncWithHeating;
|
otOptions[FPSTR(S_CH2_ALWAYS_ENABLED)] = src.opentherm.options.ch2AlwaysEnabled;
|
||||||
opentherm[FPSTR(S_GET_MIN_MAX_TEMP)] = src.opentherm.getMinMaxTemp;
|
otOptions[FPSTR(S_HEATING_TO_CH2)] = src.opentherm.options.heatingToCh2;
|
||||||
opentherm[FPSTR(S_NATIVE_HEATING_CONTROL)] = src.opentherm.nativeHeatingControl;
|
otOptions[FPSTR(S_DHW_TO_CH2)] = src.opentherm.options.dhwToCh2;
|
||||||
opentherm[FPSTR(S_IMMERGAS_FIX)] = src.opentherm.immergasFix;
|
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>();
|
auto mqtt = dst[FPSTR(S_MQTT)].to<JsonObject>();
|
||||||
mqtt[FPSTR(S_ENABLED)] = src.mqtt.enabled;
|
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>()) {
|
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_SUPPORT)].is<bool>()) {
|
||||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_PRESENT)].as<bool>();
|
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_SUPPORT)].as<bool>();
|
||||||
|
|
||||||
if (value != dst.opentherm.dhwPresent) {
|
if (value != dst.opentherm.options.dhwSupport) {
|
||||||
dst.opentherm.dhwPresent = value;
|
dst.opentherm.options.dhwSupport = value;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_SUMMER_WINTER_MODE)].is<bool>()) {
|
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_COOLING_SUPPORT)].is<bool>()) {
|
||||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_SUMMER_WINTER_MODE)].as<bool>();
|
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_COOLING_SUPPORT)].as<bool>();
|
||||||
|
|
||||||
if (value != dst.opentherm.summerWinterMode) {
|
if (value != dst.opentherm.options.coolingSupport) {
|
||||||
dst.opentherm.summerWinterMode = value;
|
dst.opentherm.options.coolingSupport = value;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_HEATING_CH2_ENABLED)].is<bool>()) {
|
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_SUMMER_WINTER_MODE)].is<bool>()) {
|
||||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_HEATING_CH2_ENABLED)].as<bool>();
|
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_SUMMER_WINTER_MODE)].as<bool>();
|
||||||
|
|
||||||
if (value != dst.opentherm.heatingCh2Enabled) {
|
if (value != dst.opentherm.options.summerWinterMode) {
|
||||||
dst.opentherm.heatingCh2Enabled = value;
|
dst.opentherm.options.summerWinterMode = value;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dst.opentherm.heatingCh2Enabled) {
|
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_HEATING_STATE_TO_SUMMER_WINTER_MODE)].is<bool>()) {
|
||||||
dst.opentherm.heatingCh1ToCh2 = false;
|
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_HEATING_STATE_TO_SUMMER_WINTER_MODE)].as<bool>();
|
||||||
dst.opentherm.dhwToCh2 = false;
|
|
||||||
|
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;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_HEATING_CH1_TO_CH2)].is<bool>()) {
|
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_HEATING_TO_CH2)].is<bool>()) {
|
||||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_HEATING_CH1_TO_CH2)].as<bool>();
|
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_HEATING_TO_CH2)].as<bool>();
|
||||||
|
|
||||||
if (value != dst.opentherm.heatingCh1ToCh2) {
|
if (value != dst.opentherm.options.heatingToCh2) {
|
||||||
dst.opentherm.heatingCh1ToCh2 = value;
|
dst.opentherm.options.heatingToCh2 = value;
|
||||||
|
|
||||||
if (dst.opentherm.heatingCh1ToCh2) {
|
if (dst.opentherm.options.heatingToCh2) {
|
||||||
dst.opentherm.heatingCh2Enabled = false;
|
dst.opentherm.options.ch2AlwaysEnabled = false;
|
||||||
dst.opentherm.dhwToCh2 = false;
|
dst.opentherm.options.dhwToCh2 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_TO_CH2)].is<bool>()) {
|
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_TO_CH2)].is<bool>()) {
|
||||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_TO_CH2)].as<bool>();
|
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_TO_CH2)].as<bool>();
|
||||||
|
|
||||||
if (value != dst.opentherm.dhwToCh2) {
|
if (value != dst.opentherm.options.dhwToCh2) {
|
||||||
dst.opentherm.dhwToCh2 = value;
|
dst.opentherm.options.dhwToCh2 = value;
|
||||||
|
|
||||||
if (dst.opentherm.dhwToCh2) {
|
if (dst.opentherm.options.dhwToCh2) {
|
||||||
dst.opentherm.heatingCh2Enabled = false;
|
dst.opentherm.options.ch2AlwaysEnabled = false;
|
||||||
dst.opentherm.heatingCh1ToCh2 = false;
|
dst.opentherm.options.heatingToCh2 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_BLOCKING)].is<bool>()) {
|
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_BLOCKING)].is<bool>()) {
|
||||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_DHW_BLOCKING)].as<bool>();
|
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_DHW_BLOCKING)].as<bool>();
|
||||||
|
|
||||||
if (value != dst.opentherm.dhwBlocking) {
|
if (value != dst.opentherm.options.dhwBlocking) {
|
||||||
dst.opentherm.dhwBlocking = value;
|
dst.opentherm.options.dhwBlocking = value;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_MODULATION_SYNC_WITH_HEATING)].is<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_MODULATION_SYNC_WITH_HEATING)].as<bool>();
|
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_MODULATION_SYNC_WITH_HEATING)].as<bool>();
|
||||||
|
|
||||||
if (value != dst.opentherm.modulationSyncWithHeating) {
|
if (value != dst.opentherm.options.modulationSyncWithHeating) {
|
||||||
dst.opentherm.modulationSyncWithHeating = value;
|
dst.opentherm.options.modulationSyncWithHeating = value;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_GET_MIN_MAX_TEMP)].is<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_GET_MIN_MAX_TEMP)].as<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) {
|
if (value != dst.opentherm.options.maxTempSyncWithTargetTemp) {
|
||||||
dst.opentherm.getMinMaxTemp = value;
|
dst.opentherm.options.maxTempSyncWithTargetTemp = value;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_NATIVE_HEATING_CONTROL)].is<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_NATIVE_HEATING_CONTROL)].as<bool>();
|
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_GET_MIN_MAX_TEMP)].as<bool>();
|
||||||
|
|
||||||
if (value != dst.opentherm.nativeHeatingControl) {
|
if (value != dst.opentherm.options.getMinMaxTemp) {
|
||||||
dst.opentherm.nativeHeatingControl = value;
|
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) {
|
if (value) {
|
||||||
dst.equitherm.enabled = false;
|
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>()) {
|
if (src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_IMMERGAS_FIX)].is<bool>()) {
|
||||||
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_IMMERGAS_FIX)].as<bool>();
|
bool value = src[FPSTR(S_OPENTHERM)][FPSTR(S_OPTIONS)][FPSTR(S_IMMERGAS_FIX)].as<bool>();
|
||||||
|
|
||||||
if (value != dst.opentherm.immergasFix) {
|
if (value != dst.opentherm.options.immergasFix) {
|
||||||
dst.opentherm.immergasFix = value;
|
dst.opentherm.options.immergasFix = value;
|
||||||
changed = true;
|
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>()) {
|
if (src[FPSTR(S_EQUITHERM)][FPSTR(S_ENABLED)].is<bool>()) {
|
||||||
bool value = src[FPSTR(S_EQUITHERM)][FPSTR(S_ENABLED)].as<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) {
|
if (value != dst.equitherm.enabled) {
|
||||||
dst.equitherm.enabled = value;
|
dst.equitherm.enabled = value;
|
||||||
changed = true;
|
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>()) {
|
if (src[FPSTR(S_PID)][FPSTR(S_ENABLED)].is<bool>()) {
|
||||||
bool value = src[FPSTR(S_PID)][FPSTR(S_ENABLED)].as<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) {
|
if (value != dst.pid.enabled) {
|
||||||
dst.pid.enabled = value;
|
dst.pid.enabled = value;
|
||||||
changed = true;
|
changed = true;
|
||||||
@@ -1326,7 +1358,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
|||||||
// force check emergency target
|
// 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;
|
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(
|
bool valid = isValidTemp(
|
||||||
value,
|
value,
|
||||||
dst.system.unitSystem,
|
dst.system.unitSystem,
|
||||||
@@ -1351,7 +1383,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
|||||||
|
|
||||||
// force check heating target
|
// 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 minTemp = indoorTempControl ? THERMOSTAT_INDOOR_MIN_TEMP : dst.heating.minTemp;
|
||||||
float maxTemp = indoorTempControl ? THERMOSTAT_INDOOR_MAX_TEMP : dst.heating.maxTemp;
|
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_PROTOCOL_VERSION)] = src.slave.appVersion;
|
||||||
slave[FPSTR(S_CONNECTED)] = src.slave.connected;
|
slave[FPSTR(S_CONNECTED)] = src.slave.connected;
|
||||||
slave[FPSTR(S_FLAME)] = src.slave.flame;
|
slave[FPSTR(S_FLAME)] = src.slave.flame;
|
||||||
|
slave[FPSTR(S_COOLING)] = src.slave.cooling;
|
||||||
|
|
||||||
auto sModulation = slave[FPSTR(S_MODULATION)].to<JsonObject>();
|
auto sModulation = slave[FPSTR(S_MODULATION)].to<JsonObject>();
|
||||||
sModulation[FPSTR(S_MIN)] = src.slave.modulation.min;
|
sModulation[FPSTR(S_MIN)] = src.slave.modulation.min;
|
||||||
|
|||||||
@@ -87,6 +87,18 @@
|
|||||||
"turbo": "Turbo mode"
|
"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": {
|
"states": {
|
||||||
"mNetworkConnected": "Network connection",
|
"mNetworkConnected": "Network connection",
|
||||||
"mMqttConnected": "MQTT connection",
|
"mMqttConnected": "MQTT connection",
|
||||||
@@ -97,8 +109,9 @@
|
|||||||
|
|
||||||
"sConnected": "OpenTherm connection",
|
"sConnected": "OpenTherm connection",
|
||||||
"sFlame": "Flame",
|
"sFlame": "Flame",
|
||||||
|
"sCooling": "Cooling",
|
||||||
"sFaultActive": "Fault",
|
"sFaultActive": "Fault",
|
||||||
"sFaultCode": "Faul code",
|
"sFaultCode": "Fault code",
|
||||||
"sDiagActive": "Diagnostic",
|
"sDiagActive": "Diagnostic",
|
||||||
"sDiagCode": "Diagnostic code",
|
"sDiagCode": "Diagnostic code",
|
||||||
|
|
||||||
@@ -356,13 +369,16 @@
|
|||||||
|
|
||||||
"options": {
|
"options": {
|
||||||
"desc": "Options",
|
"desc": "Options",
|
||||||
"dhwPresent": "DHW present",
|
"dhwSupport": "DHW support",
|
||||||
|
"coolingSupport": "Cooling support",
|
||||||
"summerWinterMode": "Summer/winter mode",
|
"summerWinterMode": "Summer/winter mode",
|
||||||
"heatingCh2Enabled": "Heating CH2 always enabled",
|
"heatingStateToSummerWinterMode": "Heating state as summer/winter mode",
|
||||||
"heatingCh1ToCh2": "Duplicate heating CH1 to CH2",
|
"ch2AlwaysEnabled": "CH2 always enabled",
|
||||||
|
"heatingToCh2": "Duplicate heating to CH2",
|
||||||
"dhwToCh2": "Duplicate DHW to CH2",
|
"dhwToCh2": "Duplicate DHW to CH2",
|
||||||
"dhwBlocking": "DHW blocking",
|
"dhwBlocking": "DHW blocking",
|
||||||
"modulationSyncWithHeating": "Sync modulation with heating",
|
"modulationSyncWithHeating": "Sync modulation with heating",
|
||||||
|
"maxTempSyncWithTargetTemp": "Sync max heating temp with target temp",
|
||||||
"getMinMaxTemp": "Get min/max temp from boiler",
|
"getMinMaxTemp": "Get min/max temp from boiler",
|
||||||
"immergasFix": "Fix for Immergas boilers"
|
"immergasFix": "Fix for Immergas boilers"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -87,6 +87,18 @@
|
|||||||
"turbo": "Турбо"
|
"turbo": "Турбо"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"notify": {
|
||||||
|
"fault": {
|
||||||
|
"title": "Состояние неисправности котла активно!",
|
||||||
|
"note": "Рекомендуется осмотреть котел и изучить документацию котла для расшифровки кода неисправности:"
|
||||||
|
},
|
||||||
|
"diag": {
|
||||||
|
"title": "Состояние диагностики котла активно!",
|
||||||
|
"note": "Возможно, вашему котлу требуется проверка? Рекомендуется изучить документацию котла для расшифровки кода диагностики:"
|
||||||
|
},
|
||||||
|
"reset": "Сбросить"
|
||||||
|
},
|
||||||
|
|
||||||
"states": {
|
"states": {
|
||||||
"mNetworkConnected": "Подключение к сети",
|
"mNetworkConnected": "Подключение к сети",
|
||||||
"mMqttConnected": "Подключение к MQTT",
|
"mMqttConnected": "Подключение к MQTT",
|
||||||
@@ -97,6 +109,7 @@
|
|||||||
|
|
||||||
"sConnected": "Подключение к OpenTherm",
|
"sConnected": "Подключение к OpenTherm",
|
||||||
"sFlame": "Пламя",
|
"sFlame": "Пламя",
|
||||||
|
"sCooling": "Охлаждение",
|
||||||
"sFaultActive": "Ошибка",
|
"sFaultActive": "Ошибка",
|
||||||
"sFaultCode": "Код ошибки",
|
"sFaultCode": "Код ошибки",
|
||||||
"sDiagActive": "Диагностика",
|
"sDiagActive": "Диагностика",
|
||||||
@@ -180,7 +193,7 @@
|
|||||||
"purpose": "Назначение",
|
"purpose": "Назначение",
|
||||||
"purposes": {
|
"purposes": {
|
||||||
"outdoorTemp": "Внешняя температура",
|
"outdoorTemp": "Внешняя температура",
|
||||||
"indoorTemp": "Внутреняя температура",
|
"indoorTemp": "Внутренняя температура",
|
||||||
"heatTemp": "Отопление, температура",
|
"heatTemp": "Отопление, температура",
|
||||||
"heatRetTemp": "Отопление, температура обратки",
|
"heatRetTemp": "Отопление, температура обратки",
|
||||||
"dhwTemp": "ГВС, температура",
|
"dhwTemp": "ГВС, температура",
|
||||||
@@ -356,13 +369,16 @@
|
|||||||
|
|
||||||
"options": {
|
"options": {
|
||||||
"desc": "Опции",
|
"desc": "Опции",
|
||||||
"dhwPresent": "Контур ГВС",
|
"dhwSupport": "Поддержка ГВС",
|
||||||
|
"coolingSupport": "Поддержка охлаждения",
|
||||||
"summerWinterMode": "Летний/зимний режим",
|
"summerWinterMode": "Летний/зимний режим",
|
||||||
"heatingCh2Enabled": "Канал 2 отопления всегда вкл.",
|
"heatingStateToSummerWinterMode": "Летний/зимний режим в качестве состояния отопления",
|
||||||
"heatingCh1ToCh2": "Дублировать параметры отопления канала 1 в канал 2",
|
"ch2AlwaysEnabled": "Канал 2 всегда вкл.",
|
||||||
|
"heatingToCh2": "Дублировать параметры отопления в канал 2",
|
||||||
"dhwToCh2": "Дублировать параметры ГВС в канал 2",
|
"dhwToCh2": "Дублировать параметры ГВС в канал 2",
|
||||||
"dhwBlocking": "DHW blocking",
|
"dhwBlocking": "DHW blocking",
|
||||||
"modulationSyncWithHeating": "Синхронизировать модуляцию с отоплением",
|
"modulationSyncWithHeating": "Синхронизировать модуляцию с отоплением",
|
||||||
|
"maxTempSyncWithTargetTemp": "Синхронизировать макс. темп. отопления с целевой темп.",
|
||||||
"getMinMaxTemp": "Получать мин. и макс. температуру от котла",
|
"getMinMaxTemp": "Получать мин. и макс. температуру от котла",
|
||||||
"immergasFix": "Фикс для котлов Immergas"
|
"immergasFix": "Фикс для котлов Immergas"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -71,6 +71,36 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
</details>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
@@ -113,6 +143,10 @@
|
|||||||
<th scope="row" data-i18n>dashboard.states.sFlame</th>
|
<th scope="row" data-i18n>dashboard.states.sFlame</th>
|
||||||
<td><i class="sFlame"></i></td>
|
<td><i class="sFlame"></i></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row" data-i18n>dashboard.states.sCooling</th>
|
||||||
|
<td><i class="sCooling"></i></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
@@ -354,6 +388,60 @@
|
|||||||
newSettings.dhw.enabled = event.currentTarget.checked;
|
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() {
|
setTimeout(async function onLoadPage() {
|
||||||
let unitSystem = null;
|
let unitSystem = null;
|
||||||
|
|
||||||
@@ -372,8 +460,8 @@
|
|||||||
(prevSettings.heating.enabled != newSettings.heating.enabled)
|
(prevSettings.heating.enabled != newSettings.heating.enabled)
|
||||||
|| (prevSettings.heating.turbo != newSettings.heating.turbo)
|
|| (prevSettings.heating.turbo != newSettings.heating.turbo)
|
||||||
|| (prevSettings.heating.target != newSettings.heating.target)
|
|| (prevSettings.heating.target != newSettings.heating.target)
|
||||||
|| (prevSettings.opentherm.dhwPresent && prevSettings.dhw.enabled != newSettings.dhw.enabled)
|
|| (prevSettings.opentherm.options.dhwSupport && prevSettings.dhw.enabled != newSettings.dhw.enabled)
|
||||||
|| (prevSettings.opentherm.dhwPresent && prevSettings.dhw.target != newSettings.dhw.target)
|
|| (prevSettings.opentherm.options.dhwSupport && prevSettings.dhw.target != newSettings.dhw.target)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (modified) {
|
if (modified) {
|
||||||
@@ -397,7 +485,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
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;
|
prevSettings = result;
|
||||||
unitSystem = result.system.unitSystem;
|
unitSystem = result.system.unitSystem;
|
||||||
newSettings.heating.enabled = result.heating.enabled;
|
newSettings.heating.enabled = result.heating.enabled;
|
||||||
@@ -406,7 +494,7 @@
|
|||||||
newSettings.dhw.enabled = result.dhw.enabled;
|
newSettings.dhw.enabled = result.dhw.enabled;
|
||||||
newSettings.dhw.target = result.dhw.target;
|
newSettings.dhw.target = result.dhw.target;
|
||||||
|
|
||||||
if (result.opentherm.dhwPresent) {
|
if (result.opentherm.options.dhwSupport) {
|
||||||
show('#thermostat-dhw');
|
show('#thermostat-dhw');
|
||||||
} else {
|
} else {
|
||||||
hide('#thermostat-dhw');
|
hide('#thermostat-dhw');
|
||||||
@@ -462,6 +550,7 @@
|
|||||||
result.slave.connected ? "green" : "red"
|
result.slave.connected ? "green" : "red"
|
||||||
);
|
);
|
||||||
setState('.sFlame', result.slave.flame);
|
setState('.sFlame', result.slave.flame);
|
||||||
|
setState('.sCooling', result.slave.cooling);
|
||||||
|
|
||||||
setValue('.sModMin', result.slave.modulation.min);
|
setValue('.sModMin', result.slave.modulation.min);
|
||||||
setValue('.sModMax', result.slave.modulation.max);
|
setValue('.sModMax', result.slave.modulation.max);
|
||||||
@@ -489,6 +578,13 @@
|
|||||||
: "-"
|
: "-"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (result.slave.fault.active) {
|
||||||
|
show(".notify-fault");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
hide('.notify-fault');
|
||||||
|
}
|
||||||
|
|
||||||
setStatus(
|
setStatus(
|
||||||
'.sDiagActive',
|
'.sDiagActive',
|
||||||
result.slave.diag.active ? "success" : "error",
|
result.slave.diag.active ? "success" : "error",
|
||||||
@@ -501,6 +597,13 @@
|
|||||||
: "-"
|
: "-"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (result.slave.diag.active) {
|
||||||
|
show(".notify-diag");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
hide('.notify-diag');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MASTER
|
// MASTER
|
||||||
setState('.mHeatEnabled', result.master.heating.enabled);
|
setState('.mHeatEnabled', result.master.heating.enabled);
|
||||||
|
|||||||
@@ -38,37 +38,37 @@
|
|||||||
|
|
||||||
<div id="network-settings-busy" aria-busy="true"></div>
|
<div id="network-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/network/settings" id="network-settings" class="hidden">
|
<form action="/api/network/settings" id="network-settings" class="hidden">
|
||||||
<label for="network-hostname">
|
<label>
|
||||||
<span data-i18n>network.params.hostname</span>
|
<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>
|
||||||
|
|
||||||
<label for="network-use-dhcp">
|
<label>
|
||||||
<input type="checkbox" id="network-use-dhcp" name="useDhcp" value="true">
|
<input type="checkbox" name="useDhcp" value="true">
|
||||||
<span data-i18n>network.params.dhcp</span>
|
<span data-i18n>network.params.dhcp</span>
|
||||||
</label>
|
</label>
|
||||||
<br />
|
<br />
|
||||||
<hr />
|
<hr />
|
||||||
<h4 data-i18n>network.section.static</h4>
|
<h4 data-i18n>network.section.static</h4>
|
||||||
|
|
||||||
<label for="network-static-ip">
|
<label>
|
||||||
<span data-i18n>network.params.ip</span>
|
<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>
|
||||||
|
|
||||||
<label for="network-static-gateway">
|
<label>
|
||||||
<span data-i18n>network.params.gateway</span>
|
<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>
|
||||||
|
|
||||||
<label for="network-static-subnet">
|
<label>
|
||||||
<span data-i18n>network.params.subnet</span>
|
<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>
|
||||||
|
|
||||||
<label for="network-static-dns">
|
<label>
|
||||||
<span data-i18n>network.params.dns</span>
|
<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>
|
</label>
|
||||||
|
|
||||||
<button type="submit" data-i18n>button.save</button>
|
<button type="submit" data-i18n>button.save</button>
|
||||||
@@ -109,19 +109,19 @@
|
|||||||
|
|
||||||
<div id="sta-settings-busy" aria-busy="true"></div>
|
<div id="sta-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/network/settings" id="sta-settings" class="hidden">
|
<form action="/api/network/settings" id="sta-settings" class="hidden">
|
||||||
<label for="sta-ssid">
|
<label>
|
||||||
<span data-i18n>network.wifi.ssid</span>
|
<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>
|
||||||
|
|
||||||
<label for="sta-password">
|
<label>
|
||||||
<span data-i18n>network.wifi.password</span>
|
<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>
|
||||||
|
|
||||||
<label for="sta-channel">
|
<label>
|
||||||
<span data-i18n>network.wifi.channel</span>
|
<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>
|
<small data-i18n>network.sta.channel.note</small>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
@@ -140,19 +140,19 @@
|
|||||||
|
|
||||||
<div id="ap-settings-busy" aria-busy="true"></div>
|
<div id="ap-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/network/settings" id="ap-settings" class="hidden">
|
<form action="/api/network/settings" id="ap-settings" class="hidden">
|
||||||
<label for="ap-ssid">
|
<label>
|
||||||
<span data-i18n>network.wifi.ssid</span>
|
<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>
|
||||||
|
|
||||||
<label for="ap-password">
|
<label>
|
||||||
<span data-i18n>network.wifi.password</span>
|
<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>
|
||||||
|
|
||||||
<label for="ap-channel">
|
<label>
|
||||||
<span data-i18n>network.wifi.channel</span>
|
<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>
|
</label>
|
||||||
|
|
||||||
<button type="submit" data-i18n>button.save</button>
|
<button type="submit" data-i18n>button.save</button>
|
||||||
@@ -179,22 +179,22 @@
|
|||||||
lang.build();
|
lang.build();
|
||||||
|
|
||||||
const fillData = (data) => {
|
const fillData = (data) => {
|
||||||
setInputValue('#network-hostname', data.hostname);
|
setInputValue("[name='hostname']", data.hostname);
|
||||||
setCheckboxValue('#network-use-dhcp', data.useDhcp);
|
setCheckboxValue("[name='useDhcp']", data.useDhcp);
|
||||||
setInputValue('#network-static-ip', data.staticConfig.ip);
|
setInputValue("[name='staticConfig[ip]']", data.staticConfig.ip);
|
||||||
setInputValue('#network-static-gateway', data.staticConfig.gateway);
|
setInputValue("[name='staticConfig[gateway]']", data.staticConfig.gateway);
|
||||||
setInputValue('#network-static-subnet', data.staticConfig.subnet);
|
setInputValue("[name='staticConfig[subnet]']", data.staticConfig.subnet);
|
||||||
setInputValue('#network-static-dns', data.staticConfig.dns);
|
setInputValue("[name='staticConfig[dns]']", data.staticConfig.dns);
|
||||||
setBusy('#network-settings-busy', '#network-settings', false);
|
setBusy('#network-settings-busy', '#network-settings', false);
|
||||||
|
|
||||||
setInputValue('#sta-ssid', data.sta.ssid);
|
setInputValue("[name='sta[ssid]']", data.sta.ssid);
|
||||||
setInputValue('#sta-password', data.sta.password);
|
setInputValue("[name='sta[password]']", data.sta.password);
|
||||||
setInputValue('#sta-channel', data.sta.channel);
|
setInputValue("[name='sta[channel]']", data.sta.channel);
|
||||||
setBusy('#sta-settings-busy', '#sta-settings', false);
|
setBusy('#sta-settings-busy', '#sta-settings', false);
|
||||||
|
|
||||||
setInputValue('#ap-ssid', data.ap.ssid);
|
setInputValue("[name='ap[ssid]']", data.ap.ssid);
|
||||||
setInputValue('#ap-password', data.ap.password);
|
setInputValue("[name='ap[password]']", data.ap.password);
|
||||||
setInputValue('#ap-channel', data.ap.channel);
|
setInputValue("[name='ap[channel]']", data.ap.channel);
|
||||||
setBusy('#ap-settings-busy', '#ap-settings', false);
|
setBusy('#ap-settings-busy', '#ap-settings', false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -134,12 +134,12 @@
|
|||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n>sensors.correction.offset</span>
|
<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>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n>sensors.correction.factor</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
@@ -159,7 +159,7 @@
|
|||||||
|
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n>sensors.filtering.factor.title</span>
|
<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>
|
<small data-i18n>sensors.filtering.factor.note</small>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -41,19 +41,19 @@
|
|||||||
<div id="portal-settings-busy" aria-busy="true"></div>
|
<div id="portal-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/settings" id="portal-settings" class="hidden">
|
<form action="/api/settings" id="portal-settings" class="hidden">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="portal-login">
|
<label>
|
||||||
<span data-i18n>settings.portal.login</span>
|
<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>
|
||||||
|
|
||||||
<label for="portal-password">
|
<label>
|
||||||
<span data-i18n>settings.portal.password</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label for="portal-auth">
|
<label>
|
||||||
<input type="checkbox" id="portal-auth" name="portal[auth]" value="true">
|
<input type="checkbox" name="portal[auth]" value="true">
|
||||||
<span data-i18n>settings.portal.auth</span>
|
<span data-i18n>settings.portal.auth</span>
|
||||||
</label>
|
</label>
|
||||||
<br />
|
<br />
|
||||||
@@ -74,20 +74,20 @@
|
|||||||
<legend data-i18n>settings.system.unit</legend>
|
<legend data-i18n>settings.system.unit</legend>
|
||||||
|
|
||||||
<label>
|
<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>
|
<span data-i18n>settings.system.metric</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<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>
|
<span data-i18n>settings.system.imperial</span>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="system-status-led-gpio">
|
<label>
|
||||||
<span data-i18n>settings.system.statusLedGpio</span>
|
<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>
|
<small data-i18n>settings.note.blankNotUse</small>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
@@ -95,19 +95,19 @@
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<legend data-i18n>settings.section.diag</legend>
|
<legend data-i18n>settings.section.diag</legend>
|
||||||
|
|
||||||
<label for="system-serial-enable">
|
<label>
|
||||||
<input type="checkbox" id="system-serial-enable" name="system[serial][enabled]" value="true">
|
<input type="checkbox" name="system[serial][enabled]" value="true">
|
||||||
<span data-i18n>settings.system.serial.enable</span>
|
<span data-i18n>settings.system.serial.enable</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="system-telnet-enable">
|
<label>
|
||||||
<input type="checkbox" id="system-telnet-enable" name="system[telnet][enabled]" value="true">
|
<input type="checkbox" name="system[telnet][enabled]" value="true">
|
||||||
<span data-i18n>settings.system.telnet.enable</span>
|
<span data-i18n>settings.system.telnet.enable</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="system-log-level">
|
<label>
|
||||||
<span data-i18n>settings.system.logLevel</span>
|
<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="0">SILENT</option>
|
||||||
<option value="1">FATAL</option>
|
<option value="1">FATAL</option>
|
||||||
<option value="2">ERROR</option>
|
<option value="2">ERROR</option>
|
||||||
@@ -120,9 +120,9 @@
|
|||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="system-serial-baudrate">
|
<label>
|
||||||
<span data-i18n>settings.system.serial.baud</span>
|
<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="9600">9600</option>
|
||||||
<option value="19200">19200</option>
|
<option value="19200">19200</option>
|
||||||
<option value="38400">38400</option>
|
<option value="38400">38400</option>
|
||||||
@@ -132,9 +132,9 @@
|
|||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="system-telnet-port">
|
<label>
|
||||||
<span data-i18n>settings.system.telnet.port.title</span>
|
<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>
|
<small data-i18n>settings.system.telnet.port.note</small>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -156,26 +156,26 @@
|
|||||||
<div id="heating-settings-busy" aria-busy="true"></div>
|
<div id="heating-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/settings" id="heating-settings" class="hidden">
|
<form action="/api/settings" id="heating-settings" class="hidden">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="heating-min-temp">
|
<label>
|
||||||
<span data-i18n>settings.temp.min</span>
|
<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>
|
||||||
|
|
||||||
<label for="heating-max-temp">
|
<label>
|
||||||
<span data-i18n>settings.temp.max</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="heating-hysteresis">
|
<label>
|
||||||
<span data-i18n>settings.heating.hyst</span>
|
<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>
|
||||||
|
|
||||||
<label for="heating-turbo-factor">
|
<label>
|
||||||
<span data-i18n>settings.heating.turboFactor</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -192,14 +192,14 @@
|
|||||||
<div id="dhw-settings-busy" aria-busy="true"></div>
|
<div id="dhw-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/settings" id="dhw-settings" class="hidden">
|
<form action="/api/settings" id="dhw-settings" class="hidden">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="dhw-min-temp">
|
<label>
|
||||||
<span data-i18n>settings.temp.min</span>
|
<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>
|
||||||
|
|
||||||
<label for="dhw-max-temp">
|
<label>
|
||||||
<span data-i18n>settings.temp.max</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -220,15 +220,15 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="emergency-target">
|
<label>
|
||||||
<span data-i18n>settings.emergency.target.title</span>
|
<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>
|
<small data-i18n>settings.emergency.target.note</small>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="emergency-treshold-time">
|
<label>
|
||||||
<span data-i18n>settings.emergency.treshold</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -245,26 +245,26 @@
|
|||||||
<div id="equitherm-settings-busy" aria-busy="true"></div>
|
<div id="equitherm-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/settings" id="equitherm-settings" class="hidden">
|
<form action="/api/settings" id="equitherm-settings" class="hidden">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="equitherm-enable">
|
<label>
|
||||||
<input type="checkbox" id="equitherm-enable" name="equitherm[enabled]" value="true">
|
<input type="checkbox" name="equitherm[enabled]" value="true">
|
||||||
<span data-i18n>settings.enable</span>
|
<span data-i18n>settings.enable</span>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="equitherm-n-factor">
|
<label>
|
||||||
<span data-i18n>settings.equitherm.n</span>
|
<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>
|
||||||
|
|
||||||
<label for="equitherm-k-factor">
|
<label>
|
||||||
<span data-i18n>settings.equitherm.k</span>
|
<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>
|
||||||
|
|
||||||
<label for="equitherm-t-factor">
|
<label>
|
||||||
<span data-i18n>settings.equitherm.t.title</span>
|
<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>
|
<small data-i18n>settings.equitherm.t.note</small>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -282,45 +282,45 @@
|
|||||||
<div id="pid-settings-busy" aria-busy="true"></div>
|
<div id="pid-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/settings" id="pid-settings" class="hidden">
|
<form action="/api/settings" id="pid-settings" class="hidden">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="pid-enable">
|
<label>
|
||||||
<input type="checkbox" id="pid-enable" name="pid[enabled]" value="true">
|
<input type="checkbox" name="pid[enabled]" value="true">
|
||||||
<span data-i18n>settings.enable</span>
|
<span data-i18n>settings.enable</span>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="pid-p-factor">
|
<label>
|
||||||
<span data-i18n>settings.pid.p</span>
|
<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>
|
||||||
|
|
||||||
<label for="pid-i-factor">
|
<label>
|
||||||
<span data-i18n>settings.pid.i</span>
|
<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>
|
||||||
|
|
||||||
<label for="pid-d-factor">
|
<label>
|
||||||
<span data-i18n>settings.pid.d</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label for="pid-dt">
|
<label>
|
||||||
<span data-i18n>settings.pid.dt</span>
|
<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>
|
</label>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="pid-min-temp">
|
<label>
|
||||||
<span data-i18n>settings.temp.min</span>
|
<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>
|
||||||
|
|
||||||
<label for="pid-max-temp">
|
<label>
|
||||||
<span data-i18n>settings.temp.max</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -336,67 +336,67 @@
|
|||||||
<details>
|
<details>
|
||||||
<summary><b data-i18n>settings.section.ot</b></summary>
|
<summary><b data-i18n>settings.section.ot</b></summary>
|
||||||
<div>
|
<div>
|
||||||
<div id="opentherm-settings-busy" aria-busy="true"></div>
|
<div id="ot-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/settings" id="opentherm-settings" class="hidden">
|
<form action="/api/settings" id="ot-settings" class="hidden">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend data-i18n>settings.system.unit</legend>
|
<legend data-i18n>settings.system.unit</legend>
|
||||||
|
|
||||||
<label>
|
<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>
|
<span data-i18n>settings.system.metric</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<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>
|
<span data-i18n>settings.system.imperial</span>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="opentherm-in-gpio">
|
<label>
|
||||||
<span data-i18n>settings.ot.inGpio</span>
|
<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>
|
||||||
|
|
||||||
<label for="opentherm-in-gpio">
|
<label>
|
||||||
<span data-i18n>settings.ot.outGpio</span>
|
<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>
|
||||||
|
|
||||||
<label for="opentherm-rx-led-gpio">
|
<label>
|
||||||
<span data-i18n>settings.ot.ledGpio</span>
|
<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>
|
<small data-i18n>settings.note.blankNotUse</small>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="opentherm-member-id-code">
|
<label>
|
||||||
<span data-i18n>settings.ot.memberId</span>
|
<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>
|
||||||
|
|
||||||
<label for="opentherm-flags">
|
<label>
|
||||||
<span data-i18n>settings.ot.flags</span>
|
<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>
|
||||||
|
|
||||||
<label for="opentherm-max-modulation">
|
<label>
|
||||||
<span data-i18n>settings.ot.maxMod</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="opentherm-min-power">
|
<label>
|
||||||
<span data-i18n>settings.ot.minPower.title</span>
|
<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>
|
<small data-i18n>settings.ot.minPower.note</small>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="opentherm-max-power">
|
<label>
|
||||||
<span data-i18n>settings.ot.maxPower.title</span>
|
<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>
|
<small data-i18n>settings.ot.maxPower.note</small>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -404,54 +404,69 @@
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<legend data-i18n>settings.ot.options.desc</legend>
|
<legend data-i18n>settings.ot.options.desc</legend>
|
||||||
|
|
||||||
<label for="opentherm-dhw-present">
|
<label>
|
||||||
<input type="checkbox" id="opentherm-dhw-present" name="opentherm[dhwPresent]" value="true">
|
<input type="checkbox" name="opentherm[options][dhwSupport]" value="true">
|
||||||
<span data-i18n>settings.ot.options.dhwPresent</span>
|
<span data-i18n>settings.ot.options.dhwSupport</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="opentherm-sw-mode">
|
<label>
|
||||||
<input type="checkbox" id="opentherm-sw-mode" name="opentherm[summerWinterMode]" value="true">
|
<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>
|
<span data-i18n>settings.ot.options.summerWinterMode</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="opentherm-heating-ch2-enabled">
|
<label>
|
||||||
<input type="checkbox" id="opentherm-heating-ch2-enabled" name="opentherm[heatingCh2Enabled]" value="true">
|
<input type="checkbox" name="opentherm[options][heatingStateToSummerWinterMode]" value="true">
|
||||||
<span data-i18n>settings.ot.options.heatingCh2Enabled</span>
|
<span data-i18n>settings.ot.options.heatingStateToSummerWinterMode</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="opentherm-heating-ch1-to-ch2">
|
<label>
|
||||||
<input type="checkbox" id="opentherm-heating-ch1-to-ch2" name="opentherm[heatingCh1ToCh2]" value="true">
|
<input type="checkbox" name="opentherm[options][ch2AlwaysEnabled]" value="true">
|
||||||
<span data-i18n>settings.ot.options.heatingCh1ToCh2</span>
|
<span data-i18n>settings.ot.options.ch2AlwaysEnabled</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="opentherm-dhw-to-ch2">
|
<label>
|
||||||
<input type="checkbox" id="opentherm-dhw-to-ch2" name="opentherm[dhwToCh2]" value="true">
|
<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>
|
<span data-i18n>settings.ot.options.dhwToCh2</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="opentherm-dhw-blocking">
|
<label>
|
||||||
<input type="checkbox" id="opentherm-dhw-blocking" name="opentherm[dhwBlocking]" value="true">
|
<input type="checkbox" name="opentherm[options][dhwBlocking]" value="true">
|
||||||
<span data-i18n>settings.ot.options.dhwBlocking</span>
|
<span data-i18n>settings.ot.options.dhwBlocking</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="opentherm-sync-modulation-with-heating">
|
<label>
|
||||||
<input type="checkbox" id="opentherm-sync-modulation-with-heating" name="opentherm[modulationSyncWithHeating]" value="true">
|
<input type="checkbox" name="opentherm[options][modulationSyncWithHeating]" value="true">
|
||||||
<span data-i18n>settings.ot.options.modulationSyncWithHeating</span>
|
<span data-i18n>settings.ot.options.modulationSyncWithHeating</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="opentherm-get-min-max-temp">
|
<label>
|
||||||
<input type="checkbox" id="opentherm-get-min-max-temp" name="opentherm[getMinMaxTemp]" value="true">
|
<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>
|
<span data-i18n>settings.ot.options.getMinMaxTemp</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="opentherm-immergas-fix">
|
<label>
|
||||||
<input type="checkbox" id="opentherm-immergas-fix" name="opentherm[immergasFix]" value="true">
|
<input type="checkbox" name="opentherm[options][immergasFix]" value="true">
|
||||||
<span data-i18n>settings.ot.options.immergasFix</span>
|
<span data-i18n>settings.ot.options.immergasFix</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<label for="opentherm-native-heating-control">
|
<label>
|
||||||
<input type="checkbox" id="opentherm-native-heating-control" name="opentherm[nativeHeatingControl]" value="true">
|
<input type="checkbox" name="opentherm[options][nativeHeatingControl]" value="true">
|
||||||
<span data-i18n>settings.ot.nativeHeating.title</span><br />
|
<span data-i18n>settings.ot.nativeHeating.title</span><br />
|
||||||
<small data-i18n>settings.ot.nativeHeating.note</small>
|
<small data-i18n>settings.ot.nativeHeating.note</small>
|
||||||
</label>
|
</label>
|
||||||
@@ -470,50 +485,50 @@
|
|||||||
<div id="mqtt-settings-busy" aria-busy="true"></div>
|
<div id="mqtt-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/settings" id="mqtt-settings" class="hidden">
|
<form action="/api/settings" id="mqtt-settings" class="hidden">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="mqtt-enable">
|
<label>
|
||||||
<input type="checkbox" id="mqtt-enable" name="mqtt[enabled]" value="true">
|
<input type="checkbox" name="mqtt[enabled]" value="true">
|
||||||
<span data-i18n>settings.enable</span>
|
<span data-i18n>settings.enable</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="mqtt-ha-discovery">
|
<label>
|
||||||
<input type="checkbox" id="mqtt-ha-discovery" name="mqtt[homeAssistantDiscovery]" value="true">
|
<input type="checkbox" name="mqtt[homeAssistantDiscovery]" value="true">
|
||||||
<span data-i18n>settings.mqtt.homeAssistantDiscovery</span>
|
<span data-i18n>settings.mqtt.homeAssistantDiscovery</span>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="mqtt-server">
|
<label>
|
||||||
<span data-i18n>settings.mqtt.server</span>
|
<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>
|
||||||
|
|
||||||
<label for="mqtt-port">
|
<label>
|
||||||
<span data-i18n>settings.mqtt.port</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="mqtt-user">
|
<label>
|
||||||
<span data-i18n>settings.mqtt.user</span>
|
<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>
|
||||||
|
|
||||||
<label for="mqtt-password">
|
<label>
|
||||||
<span data-i18n>settings.mqtt.password</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="mqtt-prefix">
|
<label>
|
||||||
<span data-i18n>settings.mqtt.prefix</span>
|
<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>
|
||||||
|
|
||||||
<label for="mqtt-interval">
|
<label>
|
||||||
<span data-i18n>settings.mqtt.interval</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -530,33 +545,33 @@
|
|||||||
<div id="extpump-settings-busy" aria-busy="true"></div>
|
<div id="extpump-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/settings" id="extpump-settings" class="hidden">
|
<form action="/api/settings" id="extpump-settings" class="hidden">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="extpump-use">
|
<label>
|
||||||
<input type="checkbox" id="extpump-use" name="externalPump[use]" value="true">
|
<input type="checkbox" name="externalPump[use]" value="true">
|
||||||
<span data-i18n>settings.extPump.use</span>
|
<span data-i18n>settings.extPump.use</span>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="extpump-gpio">
|
<label>
|
||||||
<span data-i18n>settings.extPump.gpio</span>
|
<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>
|
||||||
|
|
||||||
<label for="extpump-pc-time">
|
<label>
|
||||||
<span data-i18n>settings.extPump.postCirculationTime</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="extpump-as-interval">
|
<label>
|
||||||
<span data-i18n>settings.extPump.antiStuckInterval</span>
|
<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>
|
||||||
|
|
||||||
<label for="extpump-as-time">
|
<label>
|
||||||
<span data-i18n>settings.extPump.antiStuckTime</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -573,74 +588,74 @@
|
|||||||
<div id="cc-settings-busy" aria-busy="true"></div>
|
<div id="cc-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/settings" id="cc-settings" class="hidden">
|
<form action="/api/settings" id="cc-settings" class="hidden">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="cc-input-enable">
|
<label>
|
||||||
<input type="checkbox" id="cc-input-enable" name="cascadeControl[input][enabled]" value="true">
|
<input type="checkbox" name="cascadeControl[input][enabled]" value="true">
|
||||||
<span data-i18n>settings.cascadeControl.input.enable</span>
|
<span data-i18n>settings.cascadeControl.input.enable</span>
|
||||||
<br />
|
<br />
|
||||||
<small data-i18n>settings.cascadeControl.input.desc</small>
|
<small data-i18n>settings.cascadeControl.input.desc</small>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="cc-input-invert-state">
|
<label>
|
||||||
<input type="checkbox" id="cc-input-invert-state" name="cascadeControl[input][invertState]" value="true">
|
<input type="checkbox" name="cascadeControl[input][invertState]" value="true">
|
||||||
<span data-i18n>settings.cascadeControl.input.invertState</span>
|
<span data-i18n>settings.cascadeControl.input.invertState</span>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="cc-input-gpio">
|
<label>
|
||||||
<span data-i18n>settings.cascadeControl.input.gpio</span>
|
<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>
|
||||||
|
|
||||||
<label for="cc-input-tt">
|
<label>
|
||||||
<span data-i18n>settings.cascadeControl.input.thresholdTime</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="cc-output-enable">
|
<label>
|
||||||
<input type="checkbox" id="cc-output-enable" name="cascadeControl[output][enabled]" value="true">
|
<input type="checkbox" name="cascadeControl[output][enabled]" value="true">
|
||||||
<span data-i18n>settings.cascadeControl.output.enable</span>
|
<span data-i18n>settings.cascadeControl.output.enable</span>
|
||||||
<br />
|
<br />
|
||||||
<small data-i18n>settings.cascadeControl.output.desc</small>
|
<small data-i18n>settings.cascadeControl.output.desc</small>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="cc-output-invert-state">
|
<label>
|
||||||
<input type="checkbox" id="cc-output-invert-state" name="cascadeControl[output][invertState]" value="true">
|
<input type="checkbox" name="cascadeControl[output][invertState]" value="true">
|
||||||
<span data-i18n>settings.cascadeControl.output.invertState</span>
|
<span data-i18n>settings.cascadeControl.output.invertState</span>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="cc-output-gpio">
|
<label>
|
||||||
<span data-i18n>settings.cascadeControl.output.gpio</span>
|
<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>
|
||||||
|
|
||||||
<label for="cc-output-tt">
|
<label>
|
||||||
<span data-i18n>settings.cascadeControl.output.thresholdTime</span>
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend data-i18n>settings.cascadeControl.output.events.desc</legend>
|
<legend data-i18n>settings.cascadeControl.output.events.desc</legend>
|
||||||
|
|
||||||
<label for="cc-on-fault">
|
<label>
|
||||||
<input type="checkbox" id="cc-on-fault" name="cascadeControl[output][onFault]" value="true">
|
<input type="checkbox" name="cascadeControl[output][onFault]" value="true">
|
||||||
<span data-i18n>settings.cascadeControl.output.events.onFault</span>
|
<span data-i18n>settings.cascadeControl.output.events.onFault</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="cc-on-loss-conn">
|
<label>
|
||||||
<input type="checkbox" id="cc-on-loss-conn" name="cascadeControl[output][onLossConnection]" value="true">
|
<input type="checkbox" name="cascadeControl[output][onLossConnection]" value="true">
|
||||||
<span data-i18n>settings.cascadeControl.output.events.onLossConnection</span>
|
<span data-i18n>settings.cascadeControl.output.events.onLossConnection</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="cc-on-enabled-heating">
|
<label>
|
||||||
<input type="checkbox" id="cc-on-enabled-heating" name="cascadeControl[output][onEnabledHeating]" value="true">
|
<input type="checkbox" name="cascadeControl[output][onEnabledHeating]" value="true">
|
||||||
<span data-i18n>settings.cascadeControl.output.events.onEnabledHeating</span>
|
<span data-i18n>settings.cascadeControl.output.events.onEnabledHeating</span>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
@@ -671,111 +686,114 @@
|
|||||||
|
|
||||||
const fillData = (data) => {
|
const fillData = (data) => {
|
||||||
// System
|
// System
|
||||||
setSelectValue('#system-log-level', data.system.logLevel);
|
setSelectValue("[name='system[logLevel]']", data.system.logLevel);
|
||||||
setCheckboxValue('#system-serial-enable', data.system.serial.enabled);
|
setCheckboxValue("[name='system[serial][enabled]']", data.system.serial.enabled);
|
||||||
setSelectValue('#system-serial-baudrate', data.system.serial.baudrate);
|
setSelectValue("[name='system[serial][baudrate]']", data.system.serial.baudrate);
|
||||||
setCheckboxValue('#system-telnet-enable', data.system.telnet.enabled);
|
setCheckboxValue("[name='system[telnet][enabled]']", data.system.telnet.enabled);
|
||||||
setInputValue('#system-telnet-port', data.system.telnet.port);
|
setInputValue("[name='system[telnet][port]']", data.system.telnet.port);
|
||||||
setRadioValue('.system-unit-system', data.system.unitSystem);
|
setRadioValue("[name='system[unitSystem]']", data.system.unitSystem);
|
||||||
setInputValue('#system-status-led-gpio', data.system.statusLedGpio < 255 ? data.system.statusLedGpio : '');
|
setInputValue("[name='system[statusLedGpio]']", data.system.statusLedGpio < 255 ? data.system.statusLedGpio : '');
|
||||||
setBusy('#system-settings-busy', '#system-settings', false);
|
setBusy('#system-settings-busy', '#system-settings', false);
|
||||||
|
|
||||||
// Portal
|
// Portal
|
||||||
setCheckboxValue('#portal-auth', data.portal.auth);
|
setCheckboxValue("[name='portal[auth]']", data.portal.auth);
|
||||||
setInputValue('#portal-login', data.portal.login);
|
setInputValue("[name='portal[login]']", data.portal.login);
|
||||||
setInputValue('#portal-password', data.portal.password);
|
setInputValue("[name='portal[password]']", data.portal.password);
|
||||||
setBusy('#portal-settings-busy', '#portal-settings', false);
|
setBusy('#portal-settings-busy', '#portal-settings', false);
|
||||||
|
|
||||||
// Opentherm
|
// Opentherm
|
||||||
setRadioValue('.opentherm-unit-system', data.opentherm.unitSystem);
|
setRadioValue("[name='opentherm[unitSystem]']", data.opentherm.unitSystem);
|
||||||
setInputValue('#opentherm-in-gpio', data.opentherm.inGpio < 255 ? data.opentherm.inGpio : '');
|
setInputValue("[name='opentherm[inGpio]']", data.opentherm.inGpio < 255 ? data.opentherm.inGpio : '');
|
||||||
setInputValue('#opentherm-out-gpio', data.opentherm.outGpio < 255 ? data.opentherm.outGpio : '');
|
setInputValue("[name='opentherm[outGpio]']", data.opentherm.outGpio < 255 ? data.opentherm.outGpio : '');
|
||||||
setInputValue('#opentherm-rx-led-gpio', data.opentherm.rxLedGpio < 255 ? data.opentherm.rxLedGpio : '');
|
setInputValue("[name='opentherm[rxLedGpio]']", data.opentherm.rxLedGpio < 255 ? data.opentherm.rxLedGpio : '');
|
||||||
setInputValue('#opentherm-member-id', data.opentherm.memberId);
|
setInputValue("[name='opentherm[memberId]']", data.opentherm.memberId);
|
||||||
setInputValue('#opentherm-flags', data.opentherm.flags);
|
setInputValue("[name='opentherm[flags]']", data.opentherm.flags);
|
||||||
setInputValue('#opentherm-max-modulation', data.opentherm.maxModulation);
|
setInputValue("[name='opentherm[maxModulation]']", data.opentherm.maxModulation);
|
||||||
setInputValue('#opentherm-min-power', data.opentherm.minPower);
|
setInputValue("[name='opentherm[minPower]']", data.opentherm.minPower);
|
||||||
setInputValue('#opentherm-max-power', data.opentherm.maxPower);
|
setInputValue("[name='opentherm[maxPower]']", data.opentherm.maxPower);
|
||||||
setCheckboxValue('#opentherm-dhw-present', data.opentherm.dhwPresent);
|
setCheckboxValue("[name='opentherm[options][dhwSupport]']", data.opentherm.options.dhwSupport);
|
||||||
setCheckboxValue('#opentherm-sw-mode', data.opentherm.summerWinterMode);
|
setCheckboxValue("[name='opentherm[options][coolingSupport]']", data.opentherm.options.coolingSupport);
|
||||||
setCheckboxValue('#opentherm-heating-ch2-enabled', data.opentherm.heatingCh2Enabled);
|
setCheckboxValue("[name='opentherm[options][summerWinterMode]']", data.opentherm.options.summerWinterMode);
|
||||||
setCheckboxValue('#opentherm-heating-ch1-to-ch2', data.opentherm.heatingCh1ToCh2);
|
setCheckboxValue("[name='opentherm[options][heatingStateToSummerWinterMode]']", data.opentherm.options.heatingStateToSummerWinterMode);
|
||||||
setCheckboxValue('#opentherm-dhw-to-ch2', data.opentherm.dhwToCh2);
|
setCheckboxValue("[name='opentherm[options][ch2AlwaysEnabled]']", data.opentherm.options.ch2AlwaysEnabled);
|
||||||
setCheckboxValue('#opentherm-dhw-blocking', data.opentherm.dhwBlocking);
|
setCheckboxValue("[name='opentherm[options][heatingToCh2]']", data.opentherm.options.heatingToCh2);
|
||||||
setCheckboxValue('#opentherm-sync-modulation-with-heating', data.opentherm.modulationSyncWithHeating);
|
setCheckboxValue("[name='opentherm[options][dhwToCh2]']", data.opentherm.options.dhwToCh2);
|
||||||
setCheckboxValue('#opentherm-get-min-max-temp', data.opentherm.getMinMaxTemp);
|
setCheckboxValue("[name='opentherm[options][dhwBlocking]']", data.opentherm.options.dhwBlocking);
|
||||||
setCheckboxValue('#opentherm-native-heating-control', data.opentherm.nativeHeatingControl);
|
setCheckboxValue("[name='opentherm[options][modulationSyncWithHeating]']", data.opentherm.options.modulationSyncWithHeating);
|
||||||
setCheckboxValue('#opentherm-immergas-fix', data.opentherm.immergasFix);
|
setCheckboxValue("[name='opentherm[options][maxTempSyncWithTargetTemp]']", data.opentherm.options.maxTempSyncWithTargetTemp);
|
||||||
setBusy('#opentherm-settings-busy', '#opentherm-settings', false);
|
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
|
// MQTT
|
||||||
setCheckboxValue('#mqtt-enable', data.mqtt.enabled);
|
setCheckboxValue("[name='mqtt[enabled]']", data.mqtt.enabled);
|
||||||
setCheckboxValue('#mqtt-ha-discovery', data.mqtt.homeAssistantDiscovery);
|
setCheckboxValue("[name='mqtt[homeAssistantDiscovery]']", data.mqtt.homeAssistantDiscovery);
|
||||||
setInputValue('#mqtt-server', data.mqtt.server);
|
setInputValue("[name='mqtt[server]']", data.mqtt.server);
|
||||||
setInputValue('#mqtt-port', data.mqtt.port);
|
setInputValue("[name='mqtt[port]']", data.mqtt.port);
|
||||||
setInputValue('#mqtt-user', data.mqtt.user);
|
setInputValue("[name='mqtt[user]']", data.mqtt.user);
|
||||||
setInputValue('#mqtt-password', data.mqtt.password);
|
setInputValue("[name='mqtt[password]']", data.mqtt.password);
|
||||||
setInputValue('#mqtt-prefix', data.mqtt.prefix);
|
setInputValue("[name='mqtt[prefix]']", data.mqtt.prefix);
|
||||||
setInputValue('#mqtt-interval', data.mqtt.interval);
|
setInputValue("[name='mqtt[interval]']", data.mqtt.interval);
|
||||||
setBusy('#mqtt-settings-busy', '#mqtt-settings', false);
|
setBusy('#mqtt-settings-busy', '#mqtt-settings', false);
|
||||||
|
|
||||||
// Extpump
|
// Extpump
|
||||||
setCheckboxValue('#extpump-use', data.externalPump.use);
|
setCheckboxValue("[name='externalPump[use]']", data.externalPump.use);
|
||||||
setInputValue('#extpump-gpio', data.externalPump.gpio < 255 ? data.externalPump.gpio : '');
|
setInputValue("[name='externalPump[gpio]']", data.externalPump.gpio < 255 ? data.externalPump.gpio : '');
|
||||||
setInputValue('#extpump-pc-time', data.externalPump.postCirculationTime);
|
setInputValue("[name='externalPump[postCirculationTime]']", data.externalPump.postCirculationTime);
|
||||||
setInputValue('#extpump-as-interval', data.externalPump.antiStuckInterval);
|
setInputValue("[name='externalPump[antiStuckInterval]']", data.externalPump.antiStuckInterval);
|
||||||
setInputValue('#extpump-as-time', data.externalPump.antiStuckTime);
|
setInputValue("[name='externalPump[antiStuckTime]']", data.externalPump.antiStuckTime);
|
||||||
setBusy('#extpump-settings-busy', '#extpump-settings', false);
|
setBusy('#extpump-settings-busy', '#extpump-settings', false);
|
||||||
|
|
||||||
// Cascade control
|
// Cascade control
|
||||||
setCheckboxValue('#cc-input-enable', data.cascadeControl.input.enabled);
|
setCheckboxValue("[name='cascadeControl[input][enabled]']", data.cascadeControl.input.enabled);
|
||||||
setInputValue('#cc-input-gpio', data.cascadeControl.input.gpio < 255 ? data.cascadeControl.input.gpio : '');
|
setInputValue("[name='cascadeControl[input][gpio]']", data.cascadeControl.input.gpio < 255 ? data.cascadeControl.input.gpio : '');
|
||||||
setCheckboxValue('#cc-input-invert-state', data.cascadeControl.input.invertState);
|
setCheckboxValue("[name='cascadeControl[input][invertState]']", data.cascadeControl.input.invertState);
|
||||||
setInputValue('#cc-input-tt', data.cascadeControl.input.thresholdTime);
|
setInputValue("[name='cascadeControl[input][thresholdTime]']", data.cascadeControl.input.thresholdTime);
|
||||||
|
|
||||||
setCheckboxValue('#cc-output-enable', data.cascadeControl.output.enabled);
|
setCheckboxValue("[name='cascadeControl[output][enabled]']", data.cascadeControl.output.enabled);
|
||||||
setInputValue('#cc-output-gpio', data.cascadeControl.output.gpio < 255 ? data.cascadeControl.output.gpio : '');
|
setInputValue("[name='cascadeControl[output][gpio]']", data.cascadeControl.output.gpio < 255 ? data.cascadeControl.output.gpio : '');
|
||||||
setCheckboxValue('#cc-output-invert-state', data.cascadeControl.output.invertState);
|
setCheckboxValue("[name='cascadeControl[output][invertState]']", data.cascadeControl.output.invertState);
|
||||||
setInputValue('#cc-output-tt', data.cascadeControl.output.thresholdTime);
|
setInputValue("[name='cascadeControl[output][thresholdTime]']", data.cascadeControl.output.thresholdTime);
|
||||||
setCheckboxValue('#cc-on-fault', data.cascadeControl.output.onFault);
|
setCheckboxValue("[name='cascadeControl[output][onFault]']", data.cascadeControl.output.onFault);
|
||||||
setCheckboxValue('#cc-on-loss-conn', data.cascadeControl.output.onLossConnection);
|
setCheckboxValue("[name='cascadeControl[output][onLossConnection]']", data.cascadeControl.output.onLossConnection);
|
||||||
setCheckboxValue('#cc-on-enabled-heating', data.cascadeControl.output.onEnabledHeating);
|
setCheckboxValue("[name='cascadeControl[output][onEnabledHeating]']", data.cascadeControl.output.onEnabledHeating);
|
||||||
setBusy('#cc-settings-busy', '#cc-settings', false);
|
setBusy('#cc-settings-busy', '#cc-settings', false);
|
||||||
|
|
||||||
// Heating
|
// Heating
|
||||||
setInputValue('#heating-min-temp', data.heating.minTemp, {
|
setInputValue("[name='heating[minTemp]']", data.heating.minTemp, {
|
||||||
"min": data.system.unitSystem == 0 ? 0 : 32,
|
"min": data.system.unitSystem == 0 ? 0 : 32,
|
||||||
"max": data.system.unitSystem == 0 ? 99 : 211
|
"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,
|
"min": data.system.unitSystem == 0 ? 1 : 33,
|
||||||
"max": data.system.unitSystem == 0 ? 100 : 212
|
"max": data.system.unitSystem == 0 ? 100 : 212
|
||||||
});
|
});
|
||||||
setInputValue('#heating-hysteresis', data.heating.hysteresis);
|
setInputValue("[name='heating[hysteresis]']", data.heating.hysteresis);
|
||||||
setInputValue('#heating-turbo-factor', data.heating.turboFactor);
|
setInputValue("[name='heating[turboFactor]']", data.heating.turboFactor);
|
||||||
setBusy('#heating-settings-busy', '#heating-settings', false);
|
setBusy('#heating-settings-busy', '#heating-settings', false);
|
||||||
|
|
||||||
// DHW
|
// DHW
|
||||||
setInputValue('#dhw-min-temp', data.dhw.minTemp, {
|
setInputValue("[name='dhw[minTemp]']", data.dhw.minTemp, {
|
||||||
"min": data.system.unitSystem == 0 ? 0 : 32,
|
"min": data.system.unitSystem == 0 ? 0 : 32,
|
||||||
"max": data.system.unitSystem == 0 ? 99 : 211
|
"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,
|
"min": data.system.unitSystem == 0 ? 1 : 33,
|
||||||
"max": data.system.unitSystem == 0 ? 100 : 212
|
"max": data.system.unitSystem == 0 ? 100 : 212
|
||||||
});
|
});
|
||||||
setBusy('#dhw-settings-busy', '#dhw-settings', false);
|
setBusy('#dhw-settings-busy', '#dhw-settings', false);
|
||||||
|
|
||||||
// Emergency mode
|
// Emergency mode
|
||||||
setInputValue('#emergency-treshold-time', data.emergency.tresholdTime);
|
setInputValue("[name='emergency[tresholdTime]']", data.emergency.tresholdTime);
|
||||||
if (data.opentherm.nativeHeatingControl) {
|
if (data.opentherm.options.nativeHeatingControl) {
|
||||||
setInputValue('#emergency-target', data.emergency.target, {
|
setInputValue("[name='emergency[target]']", data.emergency.target, {
|
||||||
"min": data.system.unitSystem == 0 ? 5 : 41,
|
"min": data.system.unitSystem == 0 ? 5 : 41,
|
||||||
"max": data.system.unitSystem == 0 ? 30 : 86
|
"max": data.system.unitSystem == 0 ? 30 : 86
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
setInputValue('#emergency-target', data.emergency.target, {
|
setInputValue("[name='emergency[target]']", data.emergency.target, {
|
||||||
"min": data.heating.minTemp,
|
"min": data.heating.minTemp,
|
||||||
"max": data.heating.maxTemp,
|
"max": data.heating.maxTemp,
|
||||||
});
|
});
|
||||||
@@ -784,23 +802,23 @@
|
|||||||
setBusy('#emergency-settings-busy', '#emergency-settings', false);
|
setBusy('#emergency-settings-busy', '#emergency-settings', false);
|
||||||
|
|
||||||
// Equitherm
|
// Equitherm
|
||||||
setCheckboxValue('#equitherm-enable', data.equitherm.enabled);
|
setCheckboxValue("[name='equitherm[enabled]']", data.equitherm.enabled);
|
||||||
setInputValue('#equitherm-n-factor', data.equitherm.n_factor);
|
setInputValue("[name='equitherm[n_factor]']", data.equitherm.n_factor);
|
||||||
setInputValue('#equitherm-k-factor', data.equitherm.k_factor);
|
setInputValue("[name='equitherm[k_factor]']", data.equitherm.k_factor);
|
||||||
setInputValue('#equitherm-t-factor', data.equitherm.t_factor);
|
setInputValue("[name='equitherm[t_factor]']", data.equitherm.t_factor);
|
||||||
setBusy('#equitherm-settings-busy', '#equitherm-settings', false);
|
setBusy('#equitherm-settings-busy', '#equitherm-settings', false);
|
||||||
|
|
||||||
// PID
|
// PID
|
||||||
setCheckboxValue('#pid-enable', data.pid.enabled);
|
setCheckboxValue("[name='pid[enabled]']", data.pid.enabled);
|
||||||
setInputValue('#pid-p-factor', data.pid.p_factor);
|
setInputValue("[name='pid[p_factor]']", data.pid.p_factor);
|
||||||
setInputValue('#pid-i-factor', data.pid.i_factor);
|
setInputValue("[name='pid[i_factor]']", data.pid.i_factor);
|
||||||
setInputValue('#pid-d-factor', data.pid.d_factor);
|
setInputValue("[name='pid[d_factor]']", data.pid.d_factor);
|
||||||
setInputValue('#pid-dt', data.pid.dt);
|
setInputValue("[name='pid[dt]']", data.pid.dt);
|
||||||
setInputValue('#pid-min-temp', data.pid.minTemp, {
|
setInputValue("[name='pid[minTemp]']", data.pid.minTemp, {
|
||||||
"min": data.equitherm.enabled ? (data.system.unitSystem == 0 ? -100 : -146) : (data.system.unitSystem == 0 ? 0 : 32),
|
"min": data.equitherm.enabled ? (data.system.unitSystem == 0 ? -100 : -146) : (data.system.unitSystem == 0 ? 0 : 32),
|
||||||
"max": (data.system.unitSystem == 0 ? 99 : 211)
|
"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),
|
"min": (data.system.unitSystem == 0 ? 0 : 33),
|
||||||
"max": (data.system.unitSystem == 0 ? 100 : 212)
|
"max": (data.system.unitSystem == 0 ? 100 : 212)
|
||||||
});
|
});
|
||||||
@@ -827,7 +845,7 @@
|
|||||||
setupForm('#emergency-settings', fillData);
|
setupForm('#emergency-settings', fillData);
|
||||||
setupForm('#equitherm-settings', fillData);
|
setupForm('#equitherm-settings', fillData);
|
||||||
setupForm('#pid-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('#mqtt-settings', fillData, ['mqtt.user', 'mqtt.password', 'mqtt.prefix']);
|
||||||
setupForm('#extpump-settings', fillData);
|
setupForm('#extpump-settings', fillData);
|
||||||
setupForm('#cc-settings', fillData);
|
setupForm('#cc-settings', fillData);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
<input type="file" name="settings" id="restore-file" accept=".json">
|
<input type="file" name="settings" id="restore-file" accept=".json">
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div class="grid">
|
<div role="group">
|
||||||
<button type="submit" data-i18n>button.restore</button>
|
<button type="submit" data-i18n>button.restore</button>
|
||||||
<button type="button" class="secondary" onclick="window.location='/api/backup/save';" data-i18n>button.backup</button>
|
<button type="button" class="secondary" onclick="window.location='/api/backup/save';" data-i18n>button.backup</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ tr.network:hover {
|
|||||||
font-family: var(--pico-font-family-monospace);
|
font-family: var(--pico-font-family-monospace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.thermostat {
|
.thermostat {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 0.5fr 2fr 0.5fr;
|
grid-template-columns: 0.5fr 2fr 0.5fr;
|
||||||
@@ -193,6 +194,92 @@ tr.network:hover {
|
|||||||
margin: 1.25rem 0;
|
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],
|
[class=icons],
|
||||||
[class^=icons-] {
|
[class^=icons-] {
|
||||||
|
|||||||