mirror of
https://github.com/Laxilef/OTGateway.git
synced 2025-12-12 19:24:27 +05:00
Compare commits
22 Commits
1.4.0-rc.1
...
1.4.0-rc.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53eaa1d7f1 | ||
|
|
a7d796e0cc | ||
|
|
4490b38130 | ||
|
|
39a29042e1 | ||
|
|
f544f01caa | ||
|
|
41cca76bfa | ||
|
|
942bc53043 | ||
|
|
1bad689b6b | ||
|
|
9e3ef7a465 | ||
|
|
a5f6749101 | ||
|
|
b07dd46f55 | ||
|
|
07ab121788 | ||
|
|
7cbc52a8b0 | ||
|
|
e090be380c | ||
|
|
0bf49d2249 | ||
|
|
a83d94d361 | ||
|
|
358980da4c | ||
|
|
f91e39d067 | ||
|
|
1d53f21d46 | ||
|
|
c225e7c2a8 | ||
|
|
6831c4331f | ||
|
|
8fb62ce8ae |
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||

|

|
||||||
<br>
|
<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)
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
- 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](#compatible-temperature-sensors))
|
- Ability to connect an external sensors to monitor outdoor and indoor temperature ([compatible sensors](https://github.com/Laxilef/OTGateway/wiki/Compatibility#temperature-sensors))
|
||||||
- Emergency mode. If the Wi-Fi connection is lost or the gateway cannot connect to the MQTT server, the mode will turn on. This mode will automatically maintain the set temperature and prevent your home from freezing. In this mode it is also possible to use equithermal curves (weather-compensated control).
|
- Emergency mode. If the Wi-Fi connection is lost or the gateway cannot connect to the MQTT server, the mode will turn on. This mode will automatically maintain the set temperature and prevent your home from freezing. In this mode it is also possible to use equithermal curves (weather-compensated control).
|
||||||
- Automatic error reset (not with all boilers)
|
- Automatic error reset (not with all boilers)
|
||||||
- Diagnostics:
|
- Diagnostics:
|
||||||
@@ -72,7 +72,7 @@ All available information and instructions can be found in the wiki:
|
|||||||
- [ESP32Scheduler](https://github.com/laxilef/ESP32Scheduler) (for ESP32)
|
- [ESP32Scheduler](https://github.com/laxilef/ESP32Scheduler) (for ESP32)
|
||||||
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson)
|
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson)
|
||||||
- [OpenTherm Library](https://github.com/ihormelnyk/opentherm_library)
|
- [OpenTherm Library](https://github.com/ihormelnyk/opentherm_library)
|
||||||
- [ArduinoMqttClient](https://github.com/arduino-libraries/ArduinoMqttClient) /
|
- [ArduinoMqttClient](https://github.com/arduino-libraries/ArduinoMqttClient)
|
||||||
- [ESPTelnet](https://github.com/LennartHennigs/ESPTelnet)
|
- [ESPTelnet](https://github.com/LennartHennigs/ESPTelnet)
|
||||||
- [FileData](https://github.com/GyverLibs/FileData)
|
- [FileData](https://github.com/GyverLibs/FileData)
|
||||||
- [GyverPID](https://github.com/GyverLibs/GyverPID)
|
- [GyverPID](https://github.com/GyverLibs/GyverPID)
|
||||||
|
|||||||
@@ -210,7 +210,7 @@
|
|||||||
• <a href="https://github.com/Laxilef/OTGateway/blob/master/LICENSE" target="_blank" class="secondary">License</a>
|
• <a href="https://github.com/Laxilef/OTGateway/blob/master/LICENSE" target="_blank" class="secondary">License</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
|
• <a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
|
• <a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/issue" target="_blank" class="secondary">Issue & questions</a>
|
• <a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary">Issue & questions</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
|
• <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
|
||||||
</small>
|
</small>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -145,7 +145,7 @@
|
|||||||
• <a href="https://github.com/Laxilef/OTGateway/blob/master/LICENSE" target="_blank" class="secondary">License</a>
|
• <a href="https://github.com/Laxilef/OTGateway/blob/master/LICENSE" target="_blank" class="secondary">License</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
|
• <a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
|
• <a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/issue" target="_blank" class="secondary">Issue & questions</a>
|
• <a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary">Issue & questions</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
|
• <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
|
||||||
</small>
|
</small>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -63,13 +63,13 @@
|
|||||||
<div id="opentherm-settings-busy" aria-busy="true"></div>
|
<div id="opentherm-settings-busy" aria-busy="true"></div>
|
||||||
<form action="/api/settings" id="opentherm-settings" class="hidden">
|
<form action="/api/settings" id="opentherm-settings" class="hidden">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="opentherm-in-pin">
|
<label for="opentherm-in-gpio">
|
||||||
In GPIO
|
In GPIO
|
||||||
<input type="number" inputmode="numeric" class="opentherm-in-pin" name="opentherm[inPin]" min="0" max="99" step="1" required>
|
<input type="number" inputmode="numeric" class="opentherm-in-gpio" name="opentherm[inGpio]" min="0" max="254" step="1">
|
||||||
</label>
|
</label>
|
||||||
<label for="opentherm-in-pin">
|
<label for="opentherm-in-gpio">
|
||||||
Out GPIO
|
Out GPIO
|
||||||
<input type="number" inputmode="numeric" class="opentherm-out-pin" name="opentherm[outPin]" min="0" max="99" step="1" required>
|
<input type="number" inputmode="numeric" class="opentherm-out-gpio" name="opentherm[outGpio]" min="0" max="254" step="1">
|
||||||
</label>
|
</label>
|
||||||
<label for="opentherm-member-id-code">
|
<label for="opentherm-member-id-code">
|
||||||
Master MemberID code
|
Master MemberID code
|
||||||
@@ -77,10 +77,6 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<mark>After changing GPIO, the ESP must be restarted for the changes to take effect.</mark>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Options</legend>
|
<legend>Options</legend>
|
||||||
<label for="opentherm-dhw-present">
|
<label for="opentherm-dhw-present">
|
||||||
@@ -190,9 +186,9 @@
|
|||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<label for="outdoor-sensor-pin">
|
<label for="outdoor-sensor-gpio">
|
||||||
GPIO
|
GPIO
|
||||||
<input type="number" inputmode="numeric" class="outdoor-sensor-pin" name="sensors[outdoor][pin]" min="0" max="99" step="1" required>
|
<input type="number" inputmode="numeric" class="outdoor-sensor-gpio" name="sensors[outdoor][gpio]" min="0" max="254" step="1">
|
||||||
</label>
|
</label>
|
||||||
<label for="outdoor-sensor-offset">
|
<label for="outdoor-sensor-offset">
|
||||||
Temp offset (calibration)
|
Temp offset (calibration)
|
||||||
@@ -229,9 +225,9 @@
|
|||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<label for="indoor-sensor-pin">
|
<label for="indoor-sensor-gpio">
|
||||||
GPIO
|
GPIO
|
||||||
<input type="number" inputmode="numeric" class="indoor-sensor-pin" name="sensors[indoor][pin]" min="0" max="99" step="1" required>
|
<input type="number" inputmode="numeric" class="indoor-sensor-gpio" name="sensors[indoor][gpio]" min="0" max="254" step="1">
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
@@ -267,9 +263,9 @@
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<label for="extpump-pin">
|
<label for="extpump-gpio">
|
||||||
Relay GPIO
|
Relay GPIO
|
||||||
<input type="number" inputmode="numeric" class="extpump-pin" name="externalPump[pin]" min="0" max="99" step="1" required>
|
<input type="number" inputmode="numeric" class="extpump-gpio" name="externalPump[gpio]" min="0" max="254" step="1">
|
||||||
</label>
|
</label>
|
||||||
<label for="extpump-pc-time">
|
<label for="extpump-pc-time">
|
||||||
Post circulation time <small>(min)</small>
|
Post circulation time <small>(min)</small>
|
||||||
@@ -333,7 +329,7 @@
|
|||||||
• <a href="https://github.com/Laxilef/OTGateway/blob/master/LICENSE" target="_blank" class="secondary">License</a>
|
• <a href="https://github.com/Laxilef/OTGateway/blob/master/LICENSE" target="_blank" class="secondary">License</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
|
• <a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
|
• <a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/issue" target="_blank" class="secondary">Issue & questions</a>
|
• <a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary">Issue & questions</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
|
• <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
|
||||||
</small>
|
</small>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
Binary file not shown.
@@ -91,7 +91,7 @@
|
|||||||
• <a href="https://github.com/Laxilef/OTGateway/blob/master/LICENSE" target="_blank" class="secondary">License</a>
|
• <a href="https://github.com/Laxilef/OTGateway/blob/master/LICENSE" target="_blank" class="secondary">License</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
|
• <a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
|
• <a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/issue" target="_blank" class="secondary">Issue & questions</a>
|
• <a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary">Issue & questions</a>
|
||||||
• <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
|
• <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
|
||||||
</small>
|
</small>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public:
|
|||||||
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) {}
|
||||||
|
~CustomOpenTherm() {}
|
||||||
|
|
||||||
CustomOpenTherm* setYieldCallback(YieldCallback callback = nullptr) {
|
CustomOpenTherm* setYieldCallback(YieldCallback callback = nullptr) {
|
||||||
this->yieldCallback = callback;
|
this->yieldCallback = callback;
|
||||||
@@ -46,7 +47,7 @@ public:
|
|||||||
|
|
||||||
unsigned long _response;
|
unsigned long _response;
|
||||||
OpenThermResponseStatus _responseStatus = OpenThermResponseStatus::NONE;
|
OpenThermResponseStatus _responseStatus = OpenThermResponseStatus::NONE;
|
||||||
if (!this->sendRequestAync(request)) {
|
if (!this->sendRequestAsync(request)) {
|
||||||
_response = 0;
|
_response = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -88,7 +89,7 @@ public:
|
|||||||
| (dhwBlocking << 6);
|
| (dhwBlocking << 6);
|
||||||
data <<= 8;
|
data <<= 8;
|
||||||
|
|
||||||
return this->sendRequest(this->buildRequest(
|
return this->sendRequest(buildRequest(
|
||||||
OpenThermMessageType::READ_DATA,
|
OpenThermMessageType::READ_DATA,
|
||||||
OpenThermMessageID::Status,
|
OpenThermMessageID::Status,
|
||||||
data
|
data
|
||||||
@@ -96,30 +97,30 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool setHeatingCh1Temp(float temperature) {
|
bool setHeatingCh1Temp(float temperature) {
|
||||||
unsigned long response = this->sendRequest(this->buildRequest(
|
unsigned long response = this->sendRequest(buildRequest(
|
||||||
OpenThermMessageType::WRITE_DATA,
|
OpenThermMessageType::WRITE_DATA,
|
||||||
OpenThermMessageID::TSet,
|
OpenThermMessageID::TSet,
|
||||||
this->temperatureToData(temperature)
|
temperatureToData(temperature)
|
||||||
));
|
));
|
||||||
|
|
||||||
return isValidResponse(response);
|
return isValidResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setHeatingCh2Temp(float temperature) {
|
bool setHeatingCh2Temp(float temperature) {
|
||||||
unsigned long response = this->sendRequest(this->buildRequest(
|
unsigned long response = this->sendRequest(buildRequest(
|
||||||
OpenThermMessageType::WRITE_DATA,
|
OpenThermMessageType::WRITE_DATA,
|
||||||
OpenThermMessageID::TsetCH2,
|
OpenThermMessageID::TsetCH2,
|
||||||
this->temperatureToData(temperature)
|
temperatureToData(temperature)
|
||||||
));
|
));
|
||||||
|
|
||||||
return isValidResponse(response);
|
return isValidResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setDhwTemp(float temperature) {
|
bool setDhwTemp(float temperature) {
|
||||||
unsigned long response = this->sendRequest(this->buildRequest(
|
unsigned long response = this->sendRequest(buildRequest(
|
||||||
OpenThermMessageType::WRITE_DATA,
|
OpenThermMessageType::WRITE_DATA,
|
||||||
OpenThermMessageID::TdhwSet,
|
OpenThermMessageID::TdhwSet,
|
||||||
this->temperatureToData(temperature)
|
temperatureToData(temperature)
|
||||||
));
|
));
|
||||||
|
|
||||||
return isValidResponse(response);
|
return isValidResponse(response);
|
||||||
@@ -128,9 +129,9 @@ public:
|
|||||||
bool sendBoilerReset() {
|
bool sendBoilerReset() {
|
||||||
unsigned int data = 1;
|
unsigned int data = 1;
|
||||||
data <<= 8;
|
data <<= 8;
|
||||||
unsigned long response = this->sendRequest(this->buildRequest(
|
unsigned long response = this->sendRequest(buildRequest(
|
||||||
OpenThermMessageType::WRITE_DATA,
|
OpenThermMessageType::WRITE_DATA,
|
||||||
OpenThermMessageID::Command,
|
OpenThermMessageID::RemoteRequest,
|
||||||
data
|
data
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -140,9 +141,9 @@ public:
|
|||||||
bool sendServiceReset() {
|
bool sendServiceReset() {
|
||||||
unsigned int data = 10;
|
unsigned int data = 10;
|
||||||
data <<= 8;
|
data <<= 8;
|
||||||
unsigned long response = this->sendRequest(this->buildRequest(
|
unsigned long response = this->sendRequest(buildRequest(
|
||||||
OpenThermMessageType::WRITE_DATA,
|
OpenThermMessageType::WRITE_DATA,
|
||||||
OpenThermMessageID::Command,
|
OpenThermMessageID::RemoteRequest,
|
||||||
data
|
data
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -152,9 +153,9 @@ public:
|
|||||||
bool sendWaterFilling() {
|
bool sendWaterFilling() {
|
||||||
unsigned int data = 2;
|
unsigned int data = 2;
|
||||||
data <<= 8;
|
data <<= 8;
|
||||||
unsigned long response = this->sendRequest(this->buildRequest(
|
unsigned long response = this->sendRequest(buildRequest(
|
||||||
OpenThermMessageType::WRITE_DATA,
|
OpenThermMessageType::WRITE_DATA,
|
||||||
OpenThermMessageID::Command,
|
OpenThermMessageID::RemoteRequest,
|
||||||
data
|
data
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -162,24 +163,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// converters
|
// converters
|
||||||
float fromF88(unsigned long response) {
|
template <class T>
|
||||||
const byte valueLB = response & 0xFF;
|
static unsigned int toFloat(const T val) {
|
||||||
const byte valueHB = (response >> 8) & 0xFF;
|
|
||||||
|
|
||||||
float value = (int8_t)valueHB;
|
|
||||||
return value + (float)valueLB / 256.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> unsigned int toF88(T val) {
|
|
||||||
return (unsigned int)(val * 256);
|
return (unsigned int)(val * 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t fromS16(unsigned long response) {
|
static short getInt(const unsigned long response) {
|
||||||
const byte valueLB = response & 0xFF;
|
return response & 0xffff;
|
||||||
const byte valueHB = (response >> 8) & 0xFF;
|
|
||||||
|
|
||||||
int16_t value = valueHB;
|
|
||||||
return ((value << 8) + valueLB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ public:
|
|||||||
Log.serrorln(
|
Log.serrorln(
|
||||||
FPSTR(L_PORTAL_OTA),
|
FPSTR(L_PORTAL_OTA),
|
||||||
F("File '%s', on writing %d bytes: %s"),
|
F("File '%s', on writing %d bytes: %s"),
|
||||||
upload.filename.c_str(), upload.totalSize, result->error
|
upload.filename.c_str(), upload.totalSize, result->error.c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
137
platformio.ini
137
platformio.ini
@@ -15,9 +15,9 @@ extra_configs = secrets.default.ini
|
|||||||
[env]
|
[env]
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
bblanchon/ArduinoJson@^7.0.3
|
bblanchon/ArduinoJson@^7.0.4
|
||||||
;ihormelnyk/OpenTherm Library@^1.1.4
|
;ihormelnyk/OpenTherm Library@^1.1.5
|
||||||
https://github.com/Laxilef/opentherm_library/archive/refs/heads/fix_start_bit.zip
|
https://github.com/Laxilef/opentherm_library/archive/refs/heads/fix_lambda.zip
|
||||||
arduino-libraries/ArduinoMqttClient@^0.1.8
|
arduino-libraries/ArduinoMqttClient@^0.1.8
|
||||||
lennarthennigs/ESP Telnet@^2.2
|
lennarthennigs/ESP Telnet@^2.2
|
||||||
gyverlibs/FileData@^1.0.2
|
gyverlibs/FileData@^1.0.2
|
||||||
@@ -30,44 +30,43 @@ build_flags =
|
|||||||
-D PIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK305
|
-D PIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK305
|
||||||
-mtext-section-literals
|
-mtext-section-literals
|
||||||
-D MQTT_CLIENT_STD_FUNCTION_CALLBACK=1
|
-D MQTT_CLIENT_STD_FUNCTION_CALLBACK=1
|
||||||
;-D DEBUG_ESP_CORE -D DEBUG_ESP_WIFI -D DEBUG_ESP_PORT=Serial
|
;-D DEBUG_ESP_CORE -D DEBUG_ESP_WIFI -D DEBUG_ESP_HTTP_SERVER -D DEBUG_ESP_PORT=Serial
|
||||||
-D USE_SERIAL=${secrets.use_serial}
|
-D USE_SERIAL=${secrets.use_serial}
|
||||||
-D USE_TELNET=${secrets.use_telnet}
|
-D USE_TELNET=${secrets.use_telnet}
|
||||||
-D DEBUG_BY_DEFAULT=${secrets.debug}
|
-D DEBUG_BY_DEFAULT=${secrets.debug}
|
||||||
-D HOSTNAME_DEFAULT='"${secrets.hostname}"'
|
-D DEFAULT_HOSTNAME='"${secrets.hostname}"'
|
||||||
-D AP_SSID_DEFAULT='"${secrets.ap_ssid}"'
|
-D DEFAULT_AP_SSID='"${secrets.ap_ssid}"'
|
||||||
-D AP_PASSWORD_DEFAULT='"${secrets.ap_password}"'
|
-D DEFAULT_AP_PASSWORD='"${secrets.ap_password}"'
|
||||||
-D STA_SSID_DEFAULT='"${secrets.sta_ssid}"'
|
-D DEFAULT_STA_SSID='"${secrets.sta_ssid}"'
|
||||||
-D STA_PASSWORD_DEFAULT='"${secrets.sta_password}"'
|
-D DEFAULT_STA_PASSWORD='"${secrets.sta_password}"'
|
||||||
-D PORTAL_LOGIN_DEFAULT='"${secrets.portal_login}"'
|
-D DEFAULT_PORTAL_LOGIN='"${secrets.portal_login}"'
|
||||||
-D PORTAL_PASSWORD_DEFAULT='"${secrets.portal_password}"'
|
-D DEFAULT_PORTAL_PASSWORD='"${secrets.portal_password}"'
|
||||||
-D MQTT_SERVER_DEFAULT='"${secrets.mqtt_server}"'
|
-D DEFAULT_MQTT_SERVER='"${secrets.mqtt_server}"'
|
||||||
-D MQTT_PORT_DEFAULT=${secrets.mqtt_port}
|
-D DEFAULT_MQTT_PORT=${secrets.mqtt_port}
|
||||||
-D MQTT_USER_DEFAULT='"${secrets.mqtt_user}"'
|
-D DEFAULT_MQTT_USER='"${secrets.mqtt_user}"'
|
||||||
-D MQTT_PASSWORD_DEFAULT='"${secrets.mqtt_password}"'
|
-D DEFAULT_MQTT_PASSWORD='"${secrets.mqtt_password}"'
|
||||||
-D MQTT_PREFIX_DEFAULT='"${secrets.mqtt_prefix}"'
|
-D DEFAULT_MQTT_PREFIX='"${secrets.mqtt_prefix}"'
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
monitor_filters = direct
|
monitor_filters = direct
|
||||||
board_build.flash_mode = dio
|
board_build.flash_mode = dio
|
||||||
board_build.filesystem = littlefs
|
board_build.filesystem = littlefs
|
||||||
version = 1.4.0-rc.15
|
version = 1.4.0-rc.19
|
||||||
|
|
||||||
; Defaults
|
; Defaults
|
||||||
[esp8266_defaults]
|
[esp8266_defaults]
|
||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
nrwiersma/ESP8266Scheduler@^1.1
|
nrwiersma/ESP8266Scheduler@^1.2
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
post:tools/build.py
|
post:tools/build.py
|
||||||
build_flags = ${env.build_flags}
|
build_flags = ${env.build_flags}
|
||||||
board_build.ldscript = eagle.flash.1m256.ld
|
board_build.ldscript = eagle.flash.4m1m.ld
|
||||||
;board_build.ldscript = eagle.flash.4m1m.ld
|
|
||||||
|
|
||||||
[esp32_defaults]
|
[esp32_defaults]
|
||||||
platform = espressif32
|
platform = espressif32@^6.5
|
||||||
board_build.partitions = esp32_partitions.csv
|
board_build.partitions = esp32_partitions.csv
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
@@ -91,12 +90,12 @@ extra_scripts = ${esp8266_defaults.extra_scripts}
|
|||||||
board_build.ldscript = ${esp8266_defaults.board_build.ldscript}
|
board_build.ldscript = ${esp8266_defaults.board_build.ldscript}
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp8266_defaults.build_flags}
|
${esp8266_defaults.build_flags}
|
||||||
-D OT_IN_PIN_DEFAULT=4
|
-D DEFAULT_OT_IN_GPIO=4
|
||||||
-D OT_OUT_PIN_DEFAULT=5
|
-D DEFAULT_OT_OUT_GPIO=5
|
||||||
-D SENSOR_OUTDOOR_PIN_DEFAULT=12
|
-D DEFAULT_SENSOR_OUTDOOR_GPIO=12
|
||||||
-D SENSOR_INDOOR_PIN_DEFAULT=14
|
-D DEFAULT_SENSOR_INDOOR_GPIO=14
|
||||||
-D LED_STATUS_PIN=13
|
-D LED_STATUS_GPIO=13
|
||||||
-D LED_OT_RX_PIN=15
|
-D LED_OT_RX_GPIO=15
|
||||||
|
|
||||||
[env:d1_mini_lite]
|
[env:d1_mini_lite]
|
||||||
platform = ${esp8266_defaults.platform}
|
platform = ${esp8266_defaults.platform}
|
||||||
@@ -107,12 +106,12 @@ extra_scripts = ${esp8266_defaults.extra_scripts}
|
|||||||
board_build.ldscript = ${esp8266_defaults.board_build.ldscript}
|
board_build.ldscript = ${esp8266_defaults.board_build.ldscript}
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp8266_defaults.build_flags}
|
${esp8266_defaults.build_flags}
|
||||||
-D OT_IN_PIN_DEFAULT=4
|
-D DEFAULT_OT_IN_GPIO=4
|
||||||
-D OT_OUT_PIN_DEFAULT=5
|
-D DEFAULT_OT_OUT_GPIO=5
|
||||||
-D SENSOR_OUTDOOR_PIN_DEFAULT=12
|
-D DEFAULT_SENSOR_OUTDOOR_GPIO=12
|
||||||
-D SENSOR_INDOOR_PIN_DEFAULT=14
|
-D DEFAULT_SENSOR_INDOOR_GPIO=14
|
||||||
-D LED_STATUS_PIN=13
|
-D LED_STATUS_GPIO=13
|
||||||
-D LED_OT_RX_PIN=15
|
-D LED_OT_RX_GPIO=15
|
||||||
|
|
||||||
[env:d1_mini_pro]
|
[env:d1_mini_pro]
|
||||||
platform = ${esp8266_defaults.platform}
|
platform = ${esp8266_defaults.platform}
|
||||||
@@ -123,12 +122,12 @@ extra_scripts = ${esp8266_defaults.extra_scripts}
|
|||||||
board_build.ldscript = ${esp8266_defaults.board_build.ldscript}
|
board_build.ldscript = ${esp8266_defaults.board_build.ldscript}
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp8266_defaults.build_flags}
|
${esp8266_defaults.build_flags}
|
||||||
-D OT_IN_PIN_DEFAULT=4
|
-D DEFAULT_OT_IN_GPIO=4
|
||||||
-D OT_OUT_PIN_DEFAULT=5
|
-D DEFAULT_OT_OUT_GPIO=5
|
||||||
-D SENSOR_OUTDOOR_PIN_DEFAULT=12
|
-D DEFAULT_SENSOR_OUTDOOR_GPIO=12
|
||||||
-D SENSOR_INDOOR_PIN_DEFAULT=14
|
-D DEFAULT_SENSOR_INDOOR_GPIO=14
|
||||||
-D LED_STATUS_PIN=13
|
-D LED_STATUS_GPIO=13
|
||||||
-D LED_OT_RX_PIN=15
|
-D LED_OT_RX_GPIO=15
|
||||||
|
|
||||||
[env:s2_mini]
|
[env:s2_mini]
|
||||||
platform = ${esp32_defaults.platform}
|
platform = ${esp32_defaults.platform}
|
||||||
@@ -139,12 +138,12 @@ lib_ignore = ${esp32_defaults.lib_ignore}
|
|||||||
extra_scripts = ${esp32_defaults.extra_scripts}
|
extra_scripts = ${esp32_defaults.extra_scripts}
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32_defaults.build_flags}
|
${esp32_defaults.build_flags}
|
||||||
-D OT_IN_PIN_DEFAULT=33
|
-D DEFAULT_OT_IN_GPIO=33
|
||||||
-D OT_OUT_PIN_DEFAULT=35
|
-D DEFAULT_OT_OUT_GPIO=35
|
||||||
-D SENSOR_OUTDOOR_PIN_DEFAULT=9
|
-D DEFAULT_SENSOR_OUTDOOR_GPIO=9
|
||||||
-D SENSOR_INDOOR_PIN_DEFAULT=7
|
-D DEFAULT_SENSOR_INDOOR_GPIO=7
|
||||||
-D LED_STATUS_PIN=11
|
-D LED_STATUS_GPIO=11
|
||||||
-D LED_OT_RX_PIN=12
|
-D LED_OT_RX_GPIO=12
|
||||||
|
|
||||||
[env:s3_mini]
|
[env:s3_mini]
|
||||||
platform = ${esp32_defaults.platform}
|
platform = ${esp32_defaults.platform}
|
||||||
@@ -158,12 +157,12 @@ extra_scripts = ${esp32_defaults.extra_scripts}
|
|||||||
build_flags =
|
build_flags =
|
||||||
${esp32_defaults.build_flags}
|
${esp32_defaults.build_flags}
|
||||||
-D USE_BLE=1
|
-D USE_BLE=1
|
||||||
-D OT_IN_PIN_DEFAULT=35
|
-D DEFAULT_OT_IN_GPIO=35
|
||||||
-D OT_OUT_PIN_DEFAULT=36
|
-D DEFAULT_OT_OUT_GPIO=36
|
||||||
-D SENSOR_OUTDOOR_PIN_DEFAULT=13
|
-D DEFAULT_SENSOR_OUTDOOR_GPIO=13
|
||||||
-D SENSOR_INDOOR_PIN_DEFAULT=12
|
-D DEFAULT_SENSOR_INDOOR_GPIO=12
|
||||||
-D LED_STATUS_PIN=11
|
-D LED_STATUS_GPIO=11
|
||||||
-D LED_OT_RX_PIN=10
|
-D LED_OT_RX_GPIO=10
|
||||||
|
|
||||||
[env:c3_mini]
|
[env:c3_mini]
|
||||||
platform = ${esp32_defaults.platform}
|
platform = ${esp32_defaults.platform}
|
||||||
@@ -179,12 +178,12 @@ build_unflags =
|
|||||||
build_flags =
|
build_flags =
|
||||||
${esp32_defaults.build_flags}
|
${esp32_defaults.build_flags}
|
||||||
-D USE_BLE=1
|
-D USE_BLE=1
|
||||||
-D OT_IN_PIN_DEFAULT=8
|
-D DEFAULT_OT_IN_GPIO=8
|
||||||
-D OT_OUT_PIN_DEFAULT=10
|
-D DEFAULT_OT_OUT_GPIO=10
|
||||||
-D SENSOR_OUTDOOR_PIN_DEFAULT=0
|
-D DEFAULT_SENSOR_OUTDOOR_GPIO=0
|
||||||
-D SENSOR_INDOOR_PIN_DEFAULT=1
|
-D DEFAULT_SENSOR_INDOOR_GPIO=1
|
||||||
-D LED_STATUS_PIN=4
|
-D LED_STATUS_GPIO=4
|
||||||
-D LED_OT_RX_PIN=5
|
-D LED_OT_RX_GPIO=5
|
||||||
|
|
||||||
[env:nodemcu_32s]
|
[env:nodemcu_32s]
|
||||||
platform = ${esp32_defaults.platform}
|
platform = ${esp32_defaults.platform}
|
||||||
@@ -198,12 +197,12 @@ extra_scripts = ${esp32_defaults.extra_scripts}
|
|||||||
build_flags =
|
build_flags =
|
||||||
${esp32_defaults.build_flags}
|
${esp32_defaults.build_flags}
|
||||||
-D USE_BLE=1
|
-D USE_BLE=1
|
||||||
-D OT_IN_PIN_DEFAULT=21
|
-D DEFAULT_OT_IN_GPIO=21
|
||||||
-D OT_OUT_PIN_DEFAULT=22
|
-D DEFAULT_OT_OUT_GPIO=22
|
||||||
-D SENSOR_OUTDOOR_PIN_DEFAULT=12
|
-D DEFAULT_SENSOR_OUTDOOR_GPIO=12
|
||||||
-D SENSOR_INDOOR_PIN_DEFAULT=13
|
-D DEFAULT_SENSOR_INDOOR_GPIO=13
|
||||||
-D LED_STATUS_PIN=2 ; 18
|
-D LED_STATUS_GPIO=2 ; 18
|
||||||
-D LED_OT_RX_PIN=19
|
-D LED_OT_RX_GPIO=19
|
||||||
;-D WOKWI=1
|
;-D WOKWI=1
|
||||||
|
|
||||||
[env:d1_mini32]
|
[env:d1_mini32]
|
||||||
@@ -218,9 +217,9 @@ extra_scripts = ${esp32_defaults.extra_scripts}
|
|||||||
build_flags =
|
build_flags =
|
||||||
${esp32_defaults.build_flags}
|
${esp32_defaults.build_flags}
|
||||||
-D USE_BLE=1
|
-D USE_BLE=1
|
||||||
-D OT_IN_PIN_DEFAULT=21
|
-D DEFAULT_OT_IN_GPIO=21
|
||||||
-D OT_OUT_PIN_DEFAULT=22
|
-D DEFAULT_OT_OUT_GPIO=22
|
||||||
-D SENSOR_OUTDOOR_PIN_DEFAULT=12
|
-D DEFAULT_SENSOR_OUTDOOR_GPIO=12
|
||||||
-D SENSOR_INDOOR_PIN_DEFAULT=18
|
-D DEFAULT_SENSOR_INDOOR_GPIO=18
|
||||||
-D LED_STATUS_PIN=2
|
-D LED_STATUS_GPIO=2
|
||||||
-D LED_OT_RX_PIN=19
|
-D LED_OT_RX_GPIO=19
|
||||||
|
|||||||
@@ -1136,6 +1136,29 @@ public:
|
|||||||
return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("heating_temp")).c_str(), doc);
|
return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("heating_temp")).c_str(), doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool publishSensorHeatingReturnTemp(bool enabledByDefault = true) {
|
||||||
|
JsonDocument doc;
|
||||||
|
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
|
||||||
|
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
|
||||||
|
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.states.otStatus, 'online', 'offline') }}");
|
||||||
|
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
|
||||||
|
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||||
|
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectId(F("heating_return_temp"));
|
||||||
|
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectId(F("heating_return_temp"));
|
||||||
|
doc[FPSTR(HA_ENTITY_CATEGORY)] = F("diagnostic");
|
||||||
|
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
|
||||||
|
doc[FPSTR(HA_STATE_CLASS)] = F("measurement");
|
||||||
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("°C");
|
||||||
|
doc[FPSTR(HA_NAME)] = F("Heating return temperature");
|
||||||
|
doc[FPSTR(HA_ICON)] = F("mdi:radiator");
|
||||||
|
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
|
||||||
|
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.temperatures.heatingReturn|float(0)|round(2) }}");
|
||||||
|
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
|
||||||
|
doc.shrinkToFit();
|
||||||
|
|
||||||
|
return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("heating_return_temp")).c_str(), doc);
|
||||||
|
}
|
||||||
|
|
||||||
bool publishSensorDhwTemp(bool enabledByDefault = true) {
|
bool publishSensorDhwTemp(bool enabledByDefault = true) {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
|
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
|
||||||
@@ -1159,6 +1182,29 @@ public:
|
|||||||
return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("dhw_temp")).c_str(), doc);
|
return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("dhw_temp")).c_str(), doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool publishSensorExhaustTemp(bool enabledByDefault = true) {
|
||||||
|
JsonDocument doc;
|
||||||
|
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
|
||||||
|
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
|
||||||
|
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.states.otStatus, 'online', 'offline') }}");
|
||||||
|
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
|
||||||
|
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
|
||||||
|
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectId(F("exhaust_temp"));
|
||||||
|
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectId(F("exhaust_temp"));
|
||||||
|
doc[FPSTR(HA_ENTITY_CATEGORY)] = F("diagnostic");
|
||||||
|
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
|
||||||
|
doc[FPSTR(HA_STATE_CLASS)] = F("measurement");
|
||||||
|
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("°C");
|
||||||
|
doc[FPSTR(HA_NAME)] = F("Exhaust temperature");
|
||||||
|
doc[FPSTR(HA_ICON)] = F("mdi:smoke");
|
||||||
|
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
|
||||||
|
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.temperatures.exhaust|float(0)|round(2) }}");
|
||||||
|
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
|
||||||
|
doc.shrinkToFit();
|
||||||
|
|
||||||
|
return this->publish(this->getTopic(FPSTR(HA_ENTITY_SENSOR), F("exhaust_temp")).c_str(), doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool publishClimateHeating(byte minTemp = 20, byte maxTemp = 90, byte currentTempSource = HaHelper::TEMP_SOURCE_HEATING, bool enabledByDefault = true) {
|
bool publishClimateHeating(byte minTemp = 20, byte maxTemp = 90, byte currentTempSource = HaHelper::TEMP_SOURCE_HEATING, bool enabledByDefault = true) {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|||||||
@@ -52,14 +52,14 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
#ifdef LED_STATUS_PIN
|
#ifdef LED_STATUS_GPIO
|
||||||
pinMode(LED_STATUS_PIN, OUTPUT);
|
pinMode(LED_STATUS_GPIO, OUTPUT);
|
||||||
digitalWrite(LED_STATUS_PIN, LOW);
|
digitalWrite(LED_STATUS_GPIO, LOW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (settings.externalPump.pin != 0) {
|
if (GPIO_IS_VALID(settings.externalPump.gpio)) {
|
||||||
pinMode(settings.externalPump.pin, OUTPUT);
|
pinMode(settings.externalPump.gpio, OUTPUT);
|
||||||
digitalWrite(settings.externalPump.pin, LOW);
|
digitalWrite(settings.externalPump.gpio, LOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +89,6 @@ protected:
|
|||||||
Log.sinfoln(FPSTR(L_MAIN), F("Restart signal received. Restart after 10 sec."));
|
Log.sinfoln(FPSTR(L_MAIN), F("Restart signal received. Restart after 10 sec."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tOt->isEnabled() && settings.opentherm.inPin > 0 && settings.opentherm.outPin > 0 && settings.opentherm.inPin != settings.opentherm.outPin) {
|
|
||||||
tOt->enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (network->isConnected()) {
|
if (network->isConnected()) {
|
||||||
vars.sensors.rssi = WiFi.RSSI();
|
vars.sensors.rssi = WiFi.RSSI();
|
||||||
|
|
||||||
@@ -140,8 +136,8 @@ protected:
|
|||||||
this->yield();
|
this->yield();
|
||||||
|
|
||||||
|
|
||||||
#ifdef LED_STATUS_PIN
|
#ifdef LED_STATUS_GPIO
|
||||||
this->ledStatus(LED_STATUS_PIN);
|
this->ledStatus(LED_STATUS_GPIO);
|
||||||
#endif
|
#endif
|
||||||
this->externalPump();
|
this->externalPump();
|
||||||
this->yield();
|
this->yield();
|
||||||
@@ -211,7 +207,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ledStatus(uint8_t ledPin) {
|
void ledStatus(uint8_t gpio) {
|
||||||
uint8_t errors[4];
|
uint8_t errors[4];
|
||||||
uint8_t errCount = 0;
|
uint8_t errCount = 0;
|
||||||
static uint8_t errPos = 0;
|
static uint8_t errPos = 0;
|
||||||
@@ -219,7 +215,7 @@ protected:
|
|||||||
static bool ledOn = false;
|
static bool ledOn = false;
|
||||||
|
|
||||||
if (!this->blinkerInitialized) {
|
if (!this->blinkerInitialized) {
|
||||||
this->blinker->init(ledPin);
|
this->blinker->init(gpio);
|
||||||
this->blinkerInitialized = true;
|
this->blinkerInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,14 +243,14 @@ protected:
|
|||||||
if (!this->blinker->running() && millis() - endBlinkTime >= 5000) {
|
if (!this->blinker->running() && millis() - endBlinkTime >= 5000) {
|
||||||
if (errCount == 0) {
|
if (errCount == 0) {
|
||||||
if (!ledOn) {
|
if (!ledOn) {
|
||||||
digitalWrite(ledPin, HIGH);
|
digitalWrite(gpio, HIGH);
|
||||||
ledOn = true;
|
ledOn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
} else if (ledOn) {
|
} else if (ledOn) {
|
||||||
digitalWrite(ledPin, LOW);
|
digitalWrite(gpio, LOW);
|
||||||
ledOn = false;
|
ledOn = false;
|
||||||
endBlinkTime = millis();
|
endBlinkTime = millis();
|
||||||
return;
|
return;
|
||||||
@@ -283,10 +279,10 @@ protected:
|
|||||||
this->heatingEnabled = true;
|
this->heatingEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!settings.externalPump.use || settings.externalPump.pin == 0) {
|
if (!settings.externalPump.use || !GPIO_IS_VALID(settings.externalPump.gpio)) {
|
||||||
if (vars.states.externalPump) {
|
if (vars.states.externalPump) {
|
||||||
if (settings.externalPump.pin != 0) {
|
if (GPIO_IS_VALID(settings.externalPump.gpio)) {
|
||||||
digitalWrite(settings.externalPump.pin, LOW);
|
digitalWrite(settings.externalPump.gpio, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.states.externalPump = false;
|
vars.states.externalPump = false;
|
||||||
@@ -300,7 +296,7 @@ protected:
|
|||||||
|
|
||||||
if (vars.states.externalPump && !this->heatingEnabled) {
|
if (vars.states.externalPump && !this->heatingEnabled) {
|
||||||
if (this->extPumpStartReason == MainTask::PumpStartReason::HEATING && millis() - this->heatingDisabledTime > (settings.externalPump.postCirculationTime * 1000u)) {
|
if (this->extPumpStartReason == MainTask::PumpStartReason::HEATING && millis() - this->heatingDisabledTime > (settings.externalPump.postCirculationTime * 1000u)) {
|
||||||
digitalWrite(settings.externalPump.pin, LOW);
|
digitalWrite(settings.externalPump.gpio, LOW);
|
||||||
|
|
||||||
vars.states.externalPump = false;
|
vars.states.externalPump = false;
|
||||||
vars.parameters.extPumpLastEnableTime = millis();
|
vars.parameters.extPumpLastEnableTime = millis();
|
||||||
@@ -308,7 +304,7 @@ protected:
|
|||||||
Log.sinfoln("EXTPUMP", F("Disabled: expired post circulation time"));
|
Log.sinfoln("EXTPUMP", F("Disabled: expired post circulation time"));
|
||||||
|
|
||||||
} else if (this->extPumpStartReason == MainTask::PumpStartReason::ANTISTUCK && millis() - this->externalPumpStartTime >= (settings.externalPump.antiStuckTime * 1000u)) {
|
} else if (this->extPumpStartReason == MainTask::PumpStartReason::ANTISTUCK && millis() - this->externalPumpStartTime >= (settings.externalPump.antiStuckTime * 1000u)) {
|
||||||
digitalWrite(settings.externalPump.pin, LOW);
|
digitalWrite(settings.externalPump.gpio, LOW);
|
||||||
|
|
||||||
vars.states.externalPump = false;
|
vars.states.externalPump = false;
|
||||||
vars.parameters.extPumpLastEnableTime = millis();
|
vars.parameters.extPumpLastEnableTime = millis();
|
||||||
@@ -324,7 +320,7 @@ protected:
|
|||||||
this->externalPumpStartTime = millis();
|
this->externalPumpStartTime = millis();
|
||||||
this->extPumpStartReason = MainTask::PumpStartReason::HEATING;
|
this->extPumpStartReason = MainTask::PumpStartReason::HEATING;
|
||||||
|
|
||||||
digitalWrite(settings.externalPump.pin, HIGH);
|
digitalWrite(settings.externalPump.gpio, HIGH);
|
||||||
|
|
||||||
Log.sinfoln("EXTPUMP", F("Enabled: heating on"));
|
Log.sinfoln("EXTPUMP", F("Enabled: heating on"));
|
||||||
|
|
||||||
@@ -333,7 +329,7 @@ protected:
|
|||||||
this->externalPumpStartTime = millis();
|
this->externalPumpStartTime = millis();
|
||||||
this->extPumpStartReason = MainTask::PumpStartReason::ANTISTUCK;
|
this->extPumpStartReason = MainTask::PumpStartReason::ANTISTUCK;
|
||||||
|
|
||||||
digitalWrite(settings.externalPump.pin, HIGH);
|
digitalWrite(settings.externalPump.gpio, HIGH);
|
||||||
|
|
||||||
Log.sinfoln("EXTPUMP", F("Enabled: anti stuck"));
|
Log.sinfoln("EXTPUMP", F("Enabled: anti stuck"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ protected:
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
int getTaskPriority() {
|
int getTaskPriority() {
|
||||||
return 1;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isReadyForSend() {
|
bool isReadyForSend() {
|
||||||
@@ -370,6 +370,8 @@ protected:
|
|||||||
// temperatures
|
// temperatures
|
||||||
this->haHelper->publishNumberIndoorTemp();
|
this->haHelper->publishNumberIndoorTemp();
|
||||||
this->haHelper->publishSensorHeatingTemp();
|
this->haHelper->publishSensorHeatingTemp();
|
||||||
|
this->haHelper->publishSensorHeatingReturnTemp(false);
|
||||||
|
this->haHelper->publishSensorExhaustTemp(false);
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
this->haHelper->publishButtonRestart(false);
|
this->haHelper->publishButtonRestart(false);
|
||||||
@@ -385,8 +387,8 @@ protected:
|
|||||||
bool isStupidMode = !settings.pid.enable && !settings.equitherm.enable;
|
bool isStupidMode = !settings.pid.enable && !settings.equitherm.enable;
|
||||||
byte heatingMinTemp = isStupidMode ? settings.heating.minTemp : 10;
|
byte heatingMinTemp = isStupidMode ? settings.heating.minTemp : 10;
|
||||||
byte heatingMaxTemp = isStupidMode ? settings.heating.maxTemp : 30;
|
byte heatingMaxTemp = isStupidMode ? settings.heating.maxTemp : 30;
|
||||||
bool editableOutdoorTemp = settings.sensors.outdoor.type == 1;
|
bool editableOutdoorTemp = settings.sensors.outdoor.type == SensorType::MANUAL;
|
||||||
bool editableIndoorTemp = settings.sensors.indoor.type == 1;
|
bool editableIndoorTemp = settings.sensors.indoor.type == SensorType::MANUAL;
|
||||||
|
|
||||||
if (force || _dhwPresent != settings.opentherm.dhwPresent) {
|
if (force || _dhwPresent != settings.opentherm.dhwPresent) {
|
||||||
_dhwPresent = settings.opentherm.dhwPresent;
|
_dhwPresent = settings.opentherm.dhwPresent;
|
||||||
|
|||||||
@@ -1,31 +1,35 @@
|
|||||||
#include <CustomOpenTherm.h>
|
#include <CustomOpenTherm.h>
|
||||||
|
|
||||||
CustomOpenTherm* ot;
|
|
||||||
extern FileData fsSettings;
|
extern FileData fsSettings;
|
||||||
|
|
||||||
class OpenThermTask : public Task {
|
class OpenThermTask : public Task {
|
||||||
public:
|
public:
|
||||||
OpenThermTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {
|
OpenThermTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {}
|
||||||
ot = new CustomOpenTherm(settings.opentherm.inPin, settings.opentherm.outPin);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void IRAM_ATTR handleInterrupt() {
|
~OpenThermTask() {
|
||||||
ot->handleInterrupt();
|
delete this->instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned short readyTime = 60000;
|
const unsigned short readyTime = 60000;
|
||||||
unsigned short dhwSetTempInterval = 60000;
|
const unsigned short dhwSetTempInterval = 60000;
|
||||||
unsigned short heatingSetTempInterval = 60000;
|
const unsigned short heatingSetTempInterval = 60000;
|
||||||
|
const unsigned int initializingInterval = 3600000;
|
||||||
|
|
||||||
|
CustomOpenTherm* instance = nullptr;
|
||||||
|
unsigned long instanceCreatedTime = 0;
|
||||||
|
byte instanceInGpio = 0;
|
||||||
|
byte instanceOutGpio = 0;
|
||||||
|
bool isInitialized = false;
|
||||||
|
unsigned long initializedTime = 0;
|
||||||
|
unsigned int initializedMemberIdCode = 0;
|
||||||
|
byte dhwFlowRateMultiplier = 1;
|
||||||
|
byte pressureMultiplier = 1;
|
||||||
bool pump = true;
|
bool pump = true;
|
||||||
unsigned long lastSuccessResponse = 0;
|
unsigned long lastSuccessResponse = 0;
|
||||||
unsigned long prevUpdateNonEssentialVars = 0;
|
unsigned long prevUpdateNonEssentialVars = 0;
|
||||||
unsigned long startupTime = millis();
|
|
||||||
unsigned long dhwSetTempTime = 0;
|
unsigned long dhwSetTempTime = 0;
|
||||||
unsigned long heatingSetTempTime = 0;
|
unsigned long heatingSetTempTime = 0;
|
||||||
byte dhwFlowRateMultiplier = 1;
|
|
||||||
byte pressureMultiplier = 1;
|
|
||||||
|
|
||||||
const char* getTaskName() {
|
const char* getTaskName() {
|
||||||
return "OpenTherm";
|
return "OpenTherm";
|
||||||
@@ -36,85 +40,81 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int getTaskPriority() {
|
int getTaskPriority() {
|
||||||
return 2;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Log.sinfoln(FPSTR(L_OT), F("Started. GPIO IN: %hhu, GPIO OUT: %hhu"), settings.opentherm.inPin, settings.opentherm.outPin);
|
#ifdef LED_OT_RX_GPIO
|
||||||
|
pinMode(LED_OT_RX_GPIO, OUTPUT);
|
||||||
|
digitalWrite(LED_OT_RX_GPIO, LOW);
|
||||||
|
#endif
|
||||||
|
|
||||||
ot->setAfterSendRequestCallback([this](unsigned long request, unsigned long response, OpenThermResponseStatus status, byte attempt) {
|
// delete instance
|
||||||
|
if (this->instance != nullptr) {
|
||||||
|
delete this->instance;
|
||||||
|
this->instance = nullptr;
|
||||||
|
Log.sinfoln(FPSTR(L_OT), F("Stopped"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GPIO_IS_VALID(settings.opentherm.inGpio) || !GPIO_IS_VALID(settings.opentherm.outGpio)) {
|
||||||
|
Log.swarningln(FPSTR(L_OT), F("Not started. GPIO IN: %hhu or GPIO OUT: %hhu is not valid"), settings.opentherm.inGpio, settings.opentherm.outGpio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create instance
|
||||||
|
this->instance = new CustomOpenTherm(settings.opentherm.inGpio, settings.opentherm.outGpio);
|
||||||
|
|
||||||
|
// flags
|
||||||
|
this->instanceCreatedTime = millis();
|
||||||
|
this->instanceInGpio = settings.opentherm.inGpio;
|
||||||
|
this->instanceOutGpio = settings.opentherm.outGpio;
|
||||||
|
this->isInitialized = false;
|
||||||
|
|
||||||
|
Log.sinfoln(FPSTR(L_OT), F("Started. GPIO IN: %hhu, GPIO OUT: %hhu"), settings.opentherm.inGpio, settings.opentherm.outGpio);
|
||||||
|
|
||||||
|
this->instance->setAfterSendRequestCallback([this](unsigned long request, unsigned long response, OpenThermResponseStatus status, byte attempt) {
|
||||||
Log.straceln(
|
Log.straceln(
|
||||||
FPSTR(L_OT),
|
FPSTR(L_OT),
|
||||||
F("ID: %4d Request: %8lx Response: %8lx Attempt: %2d Status: %s"),
|
F("ID: %4d Request: %8lx Response: %8lx Attempt: %2d Status: %s"),
|
||||||
ot->getDataID(request), request, response, attempt, ot->statusToString(status)
|
CustomOpenTherm::getDataID(request), request, response, attempt, CustomOpenTherm::statusToString(status)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (status == OpenThermResponseStatus::SUCCESS) {
|
if (status == OpenThermResponseStatus::SUCCESS) {
|
||||||
this->lastSuccessResponse = millis();
|
this->lastSuccessResponse = millis();
|
||||||
|
|
||||||
#ifdef LED_OT_RX_PIN
|
#ifdef LED_OT_RX_GPIO
|
||||||
{
|
{
|
||||||
digitalWrite(LED_OT_RX_PIN, HIGH);
|
digitalWrite(LED_OT_RX_GPIO, HIGH);
|
||||||
delayMicroseconds(2000);
|
delayMicroseconds(2000);
|
||||||
digitalWrite(LED_OT_RX_PIN, LOW);
|
digitalWrite(LED_OT_RX_GPIO, LOW);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ot->setYieldCallback([this]() {
|
this->instance->setYieldCallback([this]() {
|
||||||
this->delay(25);
|
this->delay(25);
|
||||||
});
|
});
|
||||||
|
|
||||||
ot->setMinWaitTimeForStartBit(20000);
|
this->instance->begin();
|
||||||
ot->begin(OpenThermTask::handleInterrupt);
|
|
||||||
|
|
||||||
#ifdef LED_OT_RX_PIN
|
|
||||||
pinMode(LED_OT_RX_PIN, OUTPUT);
|
|
||||||
digitalWrite(LED_OT_RX_PIN, LOW);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void initBoiler() {
|
|
||||||
this->dhwFlowRateMultiplier = 1;
|
|
||||||
this->pressureMultiplier = 1;
|
|
||||||
|
|
||||||
// Not all boilers support these, only try once when the boiler becomes connected
|
|
||||||
if (updateSlaveVersion()) {
|
|
||||||
Log.straceln(FPSTR(L_OT), F("Slave version: %u, type: %u"), vars.parameters.slaveVersion, vars.parameters.slaveType);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Log.swarningln(FPSTR(L_OT), F("Get slave version failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0x013F
|
|
||||||
if (setMasterVersion(0x3F, 0x01)) {
|
|
||||||
Log.straceln(FPSTR(L_OT), F("Master version: %u, type: %u"), vars.parameters.masterVersion, vars.parameters.masterType);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Log.swarningln(FPSTR(L_OT), F("Set master version failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updateSlaveConfig()) {
|
|
||||||
Log.straceln(FPSTR(L_OT), F("Slave member id: %u, flags: %u"), vars.parameters.slaveMemberId, vars.parameters.slaveFlags);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Log.swarningln(FPSTR(L_OT), F("Get slave config failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setMasterConfig(settings.opentherm.memberIdCode & 0xFF, (settings.opentherm.memberIdCode & 0xFFFF) >> 8)) {
|
|
||||||
Log.straceln(FPSTR(L_OT), F("Master member id: %u, flags: %u"), vars.parameters.masterMemberId, vars.parameters.masterFlags);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Log.swarningln(FPSTR(L_OT), F("Set master config failed"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
static byte currentHeatingTemp, currentDhwTemp = 0;
|
static byte currentHeatingTemp, currentDhwTemp = 0;
|
||||||
unsigned long localResponse;
|
|
||||||
|
|
||||||
bool heatingEnabled = (vars.states.emergency || settings.heating.enable) && this->pump && isReady();
|
if (this->instanceInGpio != settings.opentherm.inGpio || this->instanceOutGpio != settings.opentherm.outGpio) {
|
||||||
|
this->setup();
|
||||||
|
|
||||||
|
} else if (this->initializedMemberIdCode != settings.opentherm.memberIdCode || millis() - this->initializedTime > this->initializingInterval) {
|
||||||
|
this->isInitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->instance == nullptr) {
|
||||||
|
this->delay(5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool heatingEnabled = (vars.states.emergency || settings.heating.enable) && this->pump && this->isReady();
|
||||||
bool heatingCh2Enabled = settings.opentherm.heatingCh2Enabled;
|
bool heatingCh2Enabled = settings.opentherm.heatingCh2Enabled;
|
||||||
if (settings.opentherm.heatingCh1ToCh2) {
|
if (settings.opentherm.heatingCh1ToCh2) {
|
||||||
heatingCh2Enabled = heatingEnabled;
|
heatingCh2Enabled = heatingEnabled;
|
||||||
@@ -123,7 +123,7 @@ protected:
|
|||||||
heatingCh2Enabled = settings.opentherm.dhwPresent && settings.dhw.enable;
|
heatingCh2Enabled = settings.opentherm.dhwPresent && settings.dhw.enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
localResponse = ot->setBoilerStatus(
|
unsigned long response = this->instance->setBoilerStatus(
|
||||||
heatingEnabled,
|
heatingEnabled,
|
||||||
settings.opentherm.dhwPresent && settings.dhw.enable,
|
settings.opentherm.dhwPresent && settings.dhw.enable,
|
||||||
false,
|
false,
|
||||||
@@ -133,20 +133,20 @@ protected:
|
|||||||
settings.opentherm.dhwBlocking
|
settings.opentherm.dhwBlocking
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!ot->isValidResponse(localResponse)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
Log.swarningln(FPSTR(L_OT), F("Invalid response after setBoilerStatus: %s"), ot->statusToString(ot->getLastResponseStatus()));
|
Log.swarningln(FPSTR(L_OT), F("Invalid response after setBoilerStatus: %s"), CustomOpenTherm::statusToString(this->instance->getLastResponseStatus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vars.states.otStatus && millis() - this->lastSuccessResponse < 1150) {
|
if (!vars.states.otStatus && millis() - this->lastSuccessResponse < 1150) {
|
||||||
Log.sinfoln(FPSTR(L_OT), F("Connected. Initializing"));
|
Log.sinfoln(FPSTR(L_OT), F("Connected"));
|
||||||
|
|
||||||
vars.states.otStatus = true;
|
vars.states.otStatus = true;
|
||||||
this->initBoiler();
|
|
||||||
|
|
||||||
} else if (vars.states.otStatus && millis() - this->lastSuccessResponse > 1150) {
|
} else if (vars.states.otStatus && millis() - this->lastSuccessResponse > 1150) {
|
||||||
Log.swarningln(FPSTR(L_OT), F("Disconnected"));
|
Log.swarningln(FPSTR(L_OT), F("Disconnected"));
|
||||||
|
|
||||||
vars.states.otStatus = false;
|
vars.states.otStatus = false;
|
||||||
|
this->isInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If boiler is disconnected, no need try setting other OT stuff
|
// If boiler is disconnected, no need try setting other OT stuff
|
||||||
@@ -160,17 +160,27 @@ protected:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this->isInitialized) {
|
||||||
|
Log.sinfoln(FPSTR(L_OT), F("Initializing..."));
|
||||||
|
this->isInitialized = true;
|
||||||
|
this->initializedTime = millis();
|
||||||
|
this->initializedMemberIdCode = settings.opentherm.memberIdCode;
|
||||||
|
this->dhwFlowRateMultiplier = 1;
|
||||||
|
this->pressureMultiplier = 1;
|
||||||
|
this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
if (vars.parameters.heatingEnabled != heatingEnabled) {
|
if (vars.parameters.heatingEnabled != heatingEnabled) {
|
||||||
this->prevUpdateNonEssentialVars = 0;
|
this->prevUpdateNonEssentialVars = 0;
|
||||||
vars.parameters.heatingEnabled = heatingEnabled;
|
vars.parameters.heatingEnabled = heatingEnabled;
|
||||||
Log.sinfoln(FPSTR(L_OT_HEATING), "%s", heatingEnabled ? F("Enabled") : F("Disabled"));
|
Log.sinfoln(FPSTR(L_OT_HEATING), "%s", heatingEnabled ? F("Enabled") : F("Disabled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.states.heating = ot->isCentralHeatingActive(localResponse);
|
vars.states.heating = CustomOpenTherm::isCentralHeatingActive(response);
|
||||||
vars.states.dhw = settings.opentherm.dhwPresent ? ot->isHotWaterActive(localResponse) : false;
|
vars.states.dhw = settings.opentherm.dhwPresent ? CustomOpenTherm::isHotWaterActive(response) : false;
|
||||||
vars.states.flame = ot->isFlameOn(localResponse);
|
vars.states.flame = CustomOpenTherm::isFlameOn(response);
|
||||||
vars.states.fault = ot->isFault(localResponse);
|
vars.states.fault = CustomOpenTherm::isFault(response);
|
||||||
vars.states.diagnostic = ot->isDiagnostic(localResponse);
|
vars.states.diagnostic = CustomOpenTherm::isDiagnostic(response);
|
||||||
|
|
||||||
// These parameters will be updated every minute
|
// These parameters will be updated every minute
|
||||||
if (millis() - this->prevUpdateNonEssentialVars > 60000) {
|
if (millis() - this->prevUpdateNonEssentialVars > 60000) {
|
||||||
@@ -243,11 +253,8 @@ protected:
|
|||||||
fsSettings.update();
|
fsSettings.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force set max heating temp
|
|
||||||
setMaxHeatingTemp(settings.heating.maxTemp);
|
|
||||||
|
|
||||||
// Get outdoor temp (if necessary)
|
// Get outdoor temp (if necessary)
|
||||||
if (settings.sensors.outdoor.type == 0) {
|
if (settings.sensors.outdoor.type == SensorType::BOILER) {
|
||||||
updateOutsideTemp();
|
updateOutsideTemp();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +270,7 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
// Get current modulation level (if necessary)
|
// Get current modulation level (if necessary)
|
||||||
if ((settings.opentherm.dhwPresent && settings.dhw.enable) || settings.heating.enable || heatingEnabled) {
|
if (vars.states.flame) {
|
||||||
updateModulationLevel();
|
updateModulationLevel();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -283,11 +290,17 @@ protected:
|
|||||||
// Get current heating temp
|
// Get current heating temp
|
||||||
updateHeatingTemp();
|
updateHeatingTemp();
|
||||||
|
|
||||||
|
// Get heating return temp
|
||||||
|
updateHeatingReturnTemp();
|
||||||
|
|
||||||
|
// Get exhaust temp
|
||||||
|
updateExhaustTemp();
|
||||||
|
|
||||||
|
|
||||||
// Fault reset action
|
// Fault reset action
|
||||||
if (vars.actions.resetFault) {
|
if (vars.actions.resetFault) {
|
||||||
if (vars.states.fault) {
|
if (vars.states.fault) {
|
||||||
if (ot->sendBoilerReset()) {
|
if (this->instance->sendBoilerReset()) {
|
||||||
Log.sinfoln(FPSTR(L_OT), F("Boiler fault reset successfully"));
|
Log.sinfoln(FPSTR(L_OT), F("Boiler fault reset successfully"));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -301,7 +314,7 @@ protected:
|
|||||||
// Diag reset action
|
// Diag reset action
|
||||||
if (vars.actions.resetDiagnostic) {
|
if (vars.actions.resetDiagnostic) {
|
||||||
if (vars.states.diagnostic) {
|
if (vars.states.diagnostic) {
|
||||||
if (ot->sendServiceReset()) {
|
if (this->instance->sendServiceReset()) {
|
||||||
Log.sinfoln(FPSTR(L_OT), F("Boiler diagnostic reset successfully"));
|
Log.sinfoln(FPSTR(L_OT), F("Boiler diagnostic reset successfully"));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -323,7 +336,7 @@ protected:
|
|||||||
Log.sinfoln(FPSTR(L_OT_DHW), F("Set temp = %u"), newDhwTemp);
|
Log.sinfoln(FPSTR(L_OT_DHW), F("Set temp = %u"), newDhwTemp);
|
||||||
|
|
||||||
// Set DHW temp
|
// Set DHW temp
|
||||||
if (ot->setDhwTemp(newDhwTemp)) {
|
if (this->instance->setDhwTemp(newDhwTemp)) {
|
||||||
currentDhwTemp = newDhwTemp;
|
currentDhwTemp = newDhwTemp;
|
||||||
this->dhwSetTempTime = millis();
|
this->dhwSetTempTime = millis();
|
||||||
|
|
||||||
@@ -333,7 +346,7 @@ protected:
|
|||||||
|
|
||||||
// Set DHW temp to CH2
|
// Set DHW temp to CH2
|
||||||
if (settings.opentherm.dhwToCh2) {
|
if (settings.opentherm.dhwToCh2) {
|
||||||
if (!ot->setHeatingCh2Temp(newDhwTemp)) {
|
if (!this->instance->setHeatingCh2Temp(newDhwTemp)) {
|
||||||
Log.swarningln(FPSTR(L_OT_DHW), F("Failed set ch2 temp"));
|
Log.swarningln(FPSTR(L_OT_DHW), F("Failed set ch2 temp"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,7 +358,7 @@ protected:
|
|||||||
Log.sinfoln(FPSTR(L_OT_HEATING), F("Set temp = %u"), vars.parameters.heatingSetpoint);
|
Log.sinfoln(FPSTR(L_OT_HEATING), F("Set temp = %u"), vars.parameters.heatingSetpoint);
|
||||||
|
|
||||||
// Set heating temp
|
// Set heating temp
|
||||||
if (ot->setHeatingCh1Temp(vars.parameters.heatingSetpoint)) {
|
if (this->instance->setHeatingCh1Temp(vars.parameters.heatingSetpoint) || this->setMaxHeatingTemp(vars.parameters.heatingSetpoint)) {
|
||||||
currentHeatingTemp = vars.parameters.heatingSetpoint;
|
currentHeatingTemp = vars.parameters.heatingSetpoint;
|
||||||
this->heatingSetTempTime = millis();
|
this->heatingSetTempTime = millis();
|
||||||
|
|
||||||
@@ -355,7 +368,7 @@ protected:
|
|||||||
|
|
||||||
// Set heating temp to CH2
|
// Set heating temp to CH2
|
||||||
if (settings.opentherm.heatingCh1ToCh2) {
|
if (settings.opentherm.heatingCh1ToCh2) {
|
||||||
if (!ot->setHeatingCh2Temp(vars.parameters.heatingSetpoint)) {
|
if (!this->instance->setHeatingCh2Temp(vars.parameters.heatingSetpoint)) {
|
||||||
Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set ch2 temp"));
|
Log.swarningln(FPSTR(L_OT_HEATING), F("Failed set ch2 temp"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -378,8 +391,40 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initialize() {
|
||||||
|
// Not all boilers support these, only try once when the boiler becomes connected
|
||||||
|
if (updateSlaveVersion()) {
|
||||||
|
Log.straceln(FPSTR(L_OT), F("Slave version: %u, type: %u"), vars.parameters.slaveVersion, vars.parameters.slaveType);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.swarningln(FPSTR(L_OT), F("Get slave version failed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0x013F
|
||||||
|
if (setMasterVersion(0x3F, 0x01)) {
|
||||||
|
Log.straceln(FPSTR(L_OT), F("Master version: %u, type: %u"), vars.parameters.masterVersion, vars.parameters.masterType);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.swarningln(FPSTR(L_OT), F("Set master version failed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateSlaveConfig()) {
|
||||||
|
Log.straceln(FPSTR(L_OT), F("Slave member id: %u, flags: %u"), vars.parameters.slaveMemberId, vars.parameters.slaveFlags);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.swarningln(FPSTR(L_OT), F("Get slave config failed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setMasterConfig(settings.opentherm.memberIdCode & 0xFF, (settings.opentherm.memberIdCode & 0xFFFF) >> 8)) {
|
||||||
|
Log.straceln(FPSTR(L_OT), F("Master member id: %u, flags: %u"), vars.parameters.masterMemberId, vars.parameters.masterFlags);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.swarningln(FPSTR(L_OT), F("Set master config failed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isReady() {
|
bool isReady() {
|
||||||
return millis() - this->startupTime > this->readyTime;
|
return millis() - this->instanceCreatedTime > this->readyTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needSetDhwTemp() {
|
bool needSetDhwTemp() {
|
||||||
@@ -391,13 +436,13 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool updateSlaveConfig() {
|
bool updateSlaveConfig() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::READ_DATA,
|
OpenThermRequestType::READ_DATA,
|
||||||
OpenThermMessageID::SConfigSMemberIDcode,
|
OpenThermMessageID::SConfigSMemberIDcode,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,69 +497,69 @@ protected:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::WRITE_DATA,
|
OpenThermRequestType::WRITE_DATA,
|
||||||
OpenThermMessageID::MConfigMMemberIDcode,
|
OpenThermMessageID::MConfigMMemberIDcode,
|
||||||
request
|
request
|
||||||
));
|
));
|
||||||
|
|
||||||
return ot->isValidResponse(response);
|
return CustomOpenTherm::isValidResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setMaxModulationLevel(byte value) {
|
bool setMaxModulationLevel(byte value) {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::WRITE_DATA,
|
OpenThermRequestType::WRITE_DATA,
|
||||||
OpenThermMessageID::MaxRelModLevelSetting,
|
OpenThermMessageID::MaxRelModLevelSetting,
|
||||||
ot->toF88(value)
|
CustomOpenTherm::toFloat(value)
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.parameters.maxModulation = ot->fromF88(response);
|
vars.parameters.maxModulation = CustomOpenTherm::getFloat(response);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateSlaveOtVersion() {
|
bool updateSlaveOtVersion() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::READ_DATA,
|
OpenThermRequestType::READ_DATA,
|
||||||
OpenThermMessageID::OpenThermVersionSlave,
|
OpenThermMessageID::OpenThermVersionSlave,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.parameters.slaveOtVersion = ot->getFloat(response);
|
vars.parameters.slaveOtVersion = CustomOpenTherm::getFloat(response);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setMasterOtVersion(float version) {
|
bool setMasterOtVersion(float version) {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::WRITE_DATA,
|
OpenThermRequestType::WRITE_DATA,
|
||||||
OpenThermMessageID::OpenThermVersionMaster,
|
OpenThermMessageID::OpenThermVersionMaster,
|
||||||
ot->toF88(version)
|
CustomOpenTherm::toFloat(version)
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.parameters.masterOtVersion = ot->fromF88(response);
|
vars.parameters.masterOtVersion = CustomOpenTherm::getFloat(response);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateSlaveVersion() {
|
bool updateSlaveVersion() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::READ_DATA,
|
OpenThermRequestType::READ_DATA,
|
||||||
OpenThermMessageID::SlaveVersion,
|
OpenThermMessageID::SlaveVersion,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,13 +570,13 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool setMasterVersion(uint8_t version, uint8_t type) {
|
bool setMasterVersion(uint8_t version, uint8_t type) {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::WRITE_DATA,
|
OpenThermRequestType::WRITE_DATA,
|
||||||
OpenThermMessageID::MasterVersion,
|
OpenThermMessageID::MasterVersion,
|
||||||
(unsigned int) version | (unsigned int) type << 8
|
(unsigned int) version | (unsigned int) type << 8
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,13 +587,13 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool updateMinMaxDhwTemp() {
|
bool updateMinMaxDhwTemp() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::READ_DATA,
|
OpenThermRequestType::READ_DATA,
|
||||||
OpenThermMessageID::TdhwSetUBTdhwSetLB,
|
OpenThermMessageID::TdhwSetUBTdhwSetLB,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,13 +611,13 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool updateMinMaxHeatingTemp() {
|
bool updateMinMaxHeatingTemp() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::READ_DATA,
|
OpenThermRequestType::READ_DATA,
|
||||||
OpenThermMessageID::MaxTSetUBMaxTSetLB,
|
OpenThermMessageID::MaxTSetUBMaxTSetLB,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,42 +634,59 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool setMaxHeatingTemp(byte value) {
|
bool setMaxHeatingTemp(byte value) {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermMessageType::WRITE_DATA,
|
OpenThermMessageType::WRITE_DATA,
|
||||||
OpenThermMessageID::MaxTSet,
|
OpenThermMessageID::MaxTSet,
|
||||||
ot->temperatureToData(value)
|
CustomOpenTherm::temperatureToData(value)
|
||||||
));
|
));
|
||||||
|
|
||||||
return ot->isValidResponse(response);
|
return CustomOpenTherm::isValidResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateOutsideTemp() {
|
bool updateOutsideTemp() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::READ_DATA,
|
OpenThermRequestType::READ_DATA,
|
||||||
OpenThermMessageID::Toutside,
|
OpenThermMessageID::Toutside,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.temperatures.outdoor = ot->getFloat(response) + settings.sensors.outdoor.offset;
|
vars.temperatures.outdoor = CustomOpenTherm::getFloat(response) + settings.sensors.outdoor.offset;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updateExhaustTemp() {
|
||||||
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
|
OpenThermRequestType::READ_DATA,
|
||||||
|
OpenThermMessageID::Texhaust,
|
||||||
|
0
|
||||||
|
));
|
||||||
|
|
||||||
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
short value = CustomOpenTherm::getInt(response);
|
||||||
|
vars.temperatures.exhaust = (value >= -40 && value <= 500) ? (float)value : 0.0f;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateHeatingTemp() {
|
bool updateHeatingTemp() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermMessageType::READ_DATA,
|
OpenThermMessageType::READ_DATA,
|
||||||
OpenThermMessageID::Tboiler,
|
OpenThermMessageID::Tboiler,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float value = ot->getFloat(response);
|
float value = CustomOpenTherm::getFloat(response);
|
||||||
if (value <= 0) {
|
if (value <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -633,19 +695,34 @@ protected:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool updateHeatingReturnTemp() {
|
||||||
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
|
OpenThermMessageType::READ_DATA,
|
||||||
|
OpenThermMessageID::Tret,
|
||||||
|
0
|
||||||
|
));
|
||||||
|
|
||||||
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vars.temperatures.heatingReturn = CustomOpenTherm::getFloat(response);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool updateDhwTemp() {
|
bool updateDhwTemp() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermMessageType::READ_DATA,
|
OpenThermMessageType::READ_DATA,
|
||||||
OpenThermMessageID::Tdhw,
|
OpenThermMessageID::Tdhw,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float value = ot->getFloat(response);
|
float value = CustomOpenTherm::getFloat(response);
|
||||||
if (value <= 0) {
|
if (value <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -655,17 +732,17 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool updateDhwFlowRate() {
|
bool updateDhwFlowRate() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermMessageType::READ_DATA,
|
OpenThermMessageType::READ_DATA,
|
||||||
OpenThermMessageID::DHWFlowRate,
|
OpenThermMessageID::DHWFlowRate,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float value = ot->getFloat(response);
|
float value = CustomOpenTherm::getFloat(response);
|
||||||
if (value > 16 && this->dhwFlowRateMultiplier != 10) {
|
if (value > 16 && this->dhwFlowRateMultiplier != 10) {
|
||||||
this->dhwFlowRateMultiplier = 10;
|
this->dhwFlowRateMultiplier = 10;
|
||||||
}
|
}
|
||||||
@@ -675,13 +752,13 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool updateFaultCode() {
|
bool updateFaultCode() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::READ_DATA,
|
OpenThermRequestType::READ_DATA,
|
||||||
OpenThermMessageID::ASFflags,
|
OpenThermMessageID::ASFflags,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,38 +767,33 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool updateModulationLevel() {
|
bool updateModulationLevel() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::READ_DATA,
|
OpenThermRequestType::READ_DATA,
|
||||||
OpenThermMessageID::RelModLevel,
|
OpenThermMessageID::RelModLevel,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float modulation = ot->fromF88(response);
|
vars.sensors.modulation = CustomOpenTherm::getFloat(response);
|
||||||
if (!vars.states.flame) {
|
|
||||||
vars.sensors.modulation = 0;
|
|
||||||
} else {
|
|
||||||
vars.sensors.modulation = modulation;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updatePressure() {
|
bool updatePressure() {
|
||||||
unsigned long response = ot->sendRequest(ot->buildRequest(
|
unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
|
||||||
OpenThermRequestType::READ_DATA,
|
OpenThermRequestType::READ_DATA,
|
||||||
OpenThermMessageID::CHPressure,
|
OpenThermMessageID::CHPressure,
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!ot->isValidResponse(response)) {
|
if (!CustomOpenTherm::isValidResponse(response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float value = ot->getFloat(response);
|
float value = CustomOpenTherm::getFloat(response);
|
||||||
if (value > 5 && this->pressureMultiplier != 10) {
|
if (value > 5 && this->pressureMultiplier != 10) {
|
||||||
this->pressureMultiplier = 10;
|
this->pressureMultiplier = 10;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ protected:
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
int getTaskPriority() {
|
int getTaskPriority() {
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ protected:
|
|||||||
float newTemp = 0;
|
float newTemp = 0;
|
||||||
|
|
||||||
// if use equitherm
|
// if use equitherm
|
||||||
if (settings.emergency.useEquitherm && settings.sensors.outdoor.type != 1) {
|
if (settings.emergency.useEquitherm && settings.sensors.outdoor.type != SensorType::MANUAL) {
|
||||||
float etResult = getEquithermTemp(settings.heating.minTemp, settings.heating.maxTemp);
|
float etResult = getEquithermTemp(settings.heating.minTemp, settings.heating.maxTemp);
|
||||||
|
|
||||||
if (fabs(prevEtResult - etResult) + 0.0001 >= 0.5) {
|
if (fabs(prevEtResult - etResult) + 0.0001 >= 0.5) {
|
||||||
@@ -97,7 +97,7 @@ protected:
|
|||||||
newTemp += prevEtResult;
|
newTemp += prevEtResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if(settings.emergency.usePid && settings.sensors.indoor.type != 1) {
|
} else if(settings.emergency.usePid && settings.sensors.indoor.type != SensorType::MANUAL) {
|
||||||
if (vars.parameters.heatingEnabled) {
|
if (vars.parameters.heatingEnabled) {
|
||||||
float pidResult = getPidTemp(
|
float pidResult = getPidTemp(
|
||||||
settings.heating.minTemp,
|
settings.heating.minTemp,
|
||||||
|
|||||||
@@ -60,33 +60,38 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
if (settings.sensors.outdoor.type == 2 && settings.sensors.outdoor.pin) {
|
bool indoorTempUpdated = false;
|
||||||
|
bool outdoorTempUpdated = false;
|
||||||
|
|
||||||
|
if (settings.sensors.outdoor.type == SensorType::DS18B20 && GPIO_IS_VALID(settings.sensors.indoor.gpio)) {
|
||||||
outdoorTemperatureSensor();
|
outdoorTemperatureSensor();
|
||||||
|
outdoorTempUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.sensors.indoor.type == 2 && settings.sensors.indoor.pin) {
|
if (settings.sensors.indoor.type == SensorType::DS18B20 && GPIO_IS_VALID(settings.sensors.indoor.gpio)) {
|
||||||
indoorTemperatureSensor();
|
indoorTemperatureSensor();
|
||||||
|
indoorTempUpdated = true;
|
||||||
}
|
}
|
||||||
|
#if USE_BLE
|
||||||
#if USE_BLE
|
else if (settings.sensors.indoor.type == SensorType::BLUETOOTH) {
|
||||||
if (settings.sensors.indoor.type == 3) {
|
indoorTemperatureBluetoothSensor();
|
||||||
bluetoothSensor();
|
indoorTempUpdated = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fabs(vars.temperatures.outdoor - this->filteredOutdoorTemp) > 0.099) {
|
if (outdoorTempUpdated && fabs(vars.temperatures.outdoor - this->filteredOutdoorTemp) > 0.099) {
|
||||||
vars.temperatures.outdoor = this->filteredOutdoorTemp + settings.sensors.outdoor.offset;
|
vars.temperatures.outdoor = this->filteredOutdoorTemp + settings.sensors.outdoor.offset;
|
||||||
Log.sinfoln(FPSTR(L_SENSORS_OUTDOOR), F("New temp: %f"), vars.temperatures.outdoor);
|
Log.sinfoln(FPSTR(L_SENSORS_OUTDOOR), F("New temp: %f"), vars.temperatures.outdoor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fabs(vars.temperatures.indoor - this->filteredIndoorTemp) > 0.099) {
|
if (indoorTempUpdated && fabs(vars.temperatures.indoor - this->filteredIndoorTemp) > 0.099) {
|
||||||
vars.temperatures.indoor = this->filteredIndoorTemp + settings.sensors.indoor.offset;
|
vars.temperatures.indoor = this->filteredIndoorTemp + settings.sensors.indoor.offset;
|
||||||
Log.sinfoln(FPSTR(L_SENSORS_INDOOR), F("New temp: %f"), vars.temperatures.indoor);
|
Log.sinfoln(FPSTR(L_SENSORS_INDOOR), F("New temp: %f"), vars.temperatures.indoor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_BLE
|
#if USE_BLE
|
||||||
void bluetoothSensor() {
|
void indoorTemperatureBluetoothSensor() {
|
||||||
static bool initBleNotify = false;
|
static bool initBleNotify = false;
|
||||||
if (!initBleSensor && millis() > 5000) {
|
if (!initBleSensor && millis() > 5000) {
|
||||||
Log.sinfoln(FPSTR(L_SENSORS_BLE), F("Init BLE"));
|
Log.sinfoln(FPSTR(L_SENSORS_BLE), F("Init BLE"));
|
||||||
@@ -204,9 +209,9 @@ protected:
|
|||||||
|
|
||||||
void outdoorTemperatureSensor() {
|
void outdoorTemperatureSensor() {
|
||||||
if (!this->initOutdoorSensor) {
|
if (!this->initOutdoorSensor) {
|
||||||
Log.sinfoln(FPSTR(L_SENSORS_OUTDOOR), F("Starting on gpio %hhu..."), settings.sensors.outdoor.pin);
|
Log.sinfoln(FPSTR(L_SENSORS_OUTDOOR), F("Starting on gpio %hhu..."), settings.sensors.outdoor.gpio);
|
||||||
|
|
||||||
this->oneWireOutdoorSensor->begin(settings.sensors.outdoor.pin);
|
this->oneWireOutdoorSensor->begin(settings.sensors.outdoor.gpio);
|
||||||
this->outdoorSensor->begin();
|
this->outdoorSensor->begin();
|
||||||
|
|
||||||
Log.straceln(
|
Log.straceln(
|
||||||
@@ -270,9 +275,9 @@ protected:
|
|||||||
|
|
||||||
void indoorTemperatureSensor() {
|
void indoorTemperatureSensor() {
|
||||||
if (!this->initIndoorSensor) {
|
if (!this->initIndoorSensor) {
|
||||||
Log.sinfoln(FPSTR(L_SENSORS_INDOOR), F("Starting on gpio %hhu..."), settings.sensors.indoor.pin);
|
Log.sinfoln(FPSTR(L_SENSORS_INDOOR), F("Starting on gpio %hhu..."), settings.sensors.indoor.gpio);
|
||||||
|
|
||||||
this->oneWireIndoorSensor->begin(settings.sensors.indoor.pin);
|
this->oneWireIndoorSensor->begin(settings.sensors.indoor.gpio);
|
||||||
this->indoorSensor->begin();
|
this->indoorSensor->begin();
|
||||||
|
|
||||||
Log.straceln(
|
Log.straceln(
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
struct NetworkSettings {
|
struct NetworkSettings {
|
||||||
char hostname[25] = HOSTNAME_DEFAULT;
|
char hostname[25] = DEFAULT_HOSTNAME;
|
||||||
bool useDhcp = true;
|
bool useDhcp = true;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -10,14 +10,14 @@ struct NetworkSettings {
|
|||||||
} staticConfig;
|
} staticConfig;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
char ssid[33] = AP_SSID_DEFAULT;
|
char ssid[33] = DEFAULT_AP_SSID;
|
||||||
char password[65] = AP_PASSWORD_DEFAULT;
|
char password[65] = DEFAULT_AP_PASSWORD;
|
||||||
byte channel = 6;
|
byte channel = 6;
|
||||||
} ap;
|
} ap;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
char ssid[33] = STA_SSID_DEFAULT;
|
char ssid[33] = DEFAULT_STA_SSID;
|
||||||
char password[65] = STA_PASSWORD_DEFAULT;
|
char password[65] = DEFAULT_STA_PASSWORD;
|
||||||
byte channel = 0;
|
byte channel = 0;
|
||||||
} sta;
|
} sta;
|
||||||
} networkSettings;
|
} networkSettings;
|
||||||
@@ -31,13 +31,13 @@ struct Settings {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool useAuth = false;
|
bool useAuth = false;
|
||||||
char login[13] = PORTAL_LOGIN_DEFAULT;
|
char login[13] = DEFAULT_PORTAL_LOGIN;
|
||||||
char password[33] = PORTAL_PASSWORD_DEFAULT;
|
char password[33] = DEFAULT_PORTAL_PASSWORD;
|
||||||
} portal;
|
} portal;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
byte inPin = OT_IN_PIN_DEFAULT;
|
byte inGpio = DEFAULT_OT_IN_GPIO;
|
||||||
byte outPin = OT_OUT_PIN_DEFAULT;
|
byte outGpio = DEFAULT_OT_OUT_GPIO;
|
||||||
unsigned int memberIdCode = 0;
|
unsigned int memberIdCode = 0;
|
||||||
bool dhwPresent = true;
|
bool dhwPresent = true;
|
||||||
bool summerWinterMode = false;
|
bool summerWinterMode = false;
|
||||||
@@ -49,11 +49,11 @@ struct Settings {
|
|||||||
} opentherm;
|
} opentherm;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
char server[81] = MQTT_SERVER_DEFAULT;
|
char server[81] = DEFAULT_MQTT_SERVER;
|
||||||
unsigned short port = MQTT_PORT_DEFAULT;
|
unsigned short port = DEFAULT_MQTT_PORT;
|
||||||
char user[33] = MQTT_USER_DEFAULT;
|
char user[33] = DEFAULT_MQTT_USER;
|
||||||
char password[33] = MQTT_PASSWORD_DEFAULT;
|
char password[33] = DEFAULT_MQTT_PASSWORD;
|
||||||
char prefix[33] = MQTT_PREFIX_DEFAULT;
|
char prefix[33] = DEFAULT_MQTT_PREFIX;
|
||||||
unsigned short interval = 5;
|
unsigned short interval = 5;
|
||||||
} mqtt;
|
} mqtt;
|
||||||
|
|
||||||
@@ -100,16 +100,14 @@ struct Settings {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct {
|
struct {
|
||||||
// 0 - boiler, 1 - manual, 2 - ds18b20
|
SensorType type = SensorType::BOILER;
|
||||||
byte type = 0;
|
byte gpio = DEFAULT_SENSOR_OUTDOOR_GPIO;
|
||||||
byte pin = SENSOR_OUTDOOR_PIN_DEFAULT;
|
|
||||||
float offset = 0.0f;
|
float offset = 0.0f;
|
||||||
} outdoor;
|
} outdoor;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
// 1 - manual, 2 - ds18b20, 3 - ble
|
SensorType type = SensorType::MANUAL;
|
||||||
byte type = 1;
|
byte gpio = DEFAULT_SENSOR_INDOOR_GPIO;
|
||||||
byte pin = SENSOR_INDOOR_PIN_DEFAULT;
|
|
||||||
uint8_t bleAddresss[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
uint8_t bleAddresss[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
float offset = 0.0f;
|
float offset = 0.0f;
|
||||||
} indoor;
|
} indoor;
|
||||||
@@ -117,7 +115,7 @@ struct Settings {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool use = false;
|
bool use = false;
|
||||||
byte pin = EXT_PUMP_PIN_DEFAULT;
|
byte gpio = DEFAULT_EXT_PUMP_GPIO;
|
||||||
unsigned short postCirculationTime = 600;
|
unsigned short postCirculationTime = 600;
|
||||||
unsigned int antiStuckInterval = 2592000;
|
unsigned int antiStuckInterval = 2592000;
|
||||||
unsigned short antiStuckTime = 300;
|
unsigned short antiStuckTime = 300;
|
||||||
@@ -155,7 +153,9 @@ struct Variables {
|
|||||||
float indoor = 0.0f;
|
float indoor = 0.0f;
|
||||||
float outdoor = 0.0f;
|
float outdoor = 0.0f;
|
||||||
float heating = 0.0f;
|
float heating = 0.0f;
|
||||||
|
float heatingReturn = 0.0f;
|
||||||
float dhw = 0.0f;
|
float dhw = 0.0f;
|
||||||
|
float exhaust = 0.0f;
|
||||||
} temperatures;
|
} temperatures;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
#define PROJECT_NAME "OpenTherm Gateway"
|
#define PROJECT_NAME "OpenTherm Gateway"
|
||||||
#define PROJECT_VERSION "1.4.0-rc.15"
|
#define PROJECT_VERSION "1.4.0-rc.19"
|
||||||
#define PROJECT_REPO "https://github.com/Laxilef/OTGateway"
|
#define PROJECT_REPO "https://github.com/Laxilef/OTGateway"
|
||||||
|
|
||||||
#define EMERGENCY_TIME_TRESHOLD 120000
|
#define EMERGENCY_TIME_TRESHOLD 120000
|
||||||
#define MQTT_RECONNECT_INTERVAL 15000
|
#define MQTT_RECONNECT_INTERVAL 15000
|
||||||
#define MQTT_KEEPALIVE 30
|
|
||||||
|
|
||||||
#define OPENTHERM_OFFLINE_TRESHOLD 10
|
|
||||||
|
|
||||||
#define EXT_SENSORS_INTERVAL 5000
|
#define EXT_SENSORS_INTERVAL 5000
|
||||||
#define EXT_SENSORS_FILTER_K 0.15
|
#define EXT_SENSORS_FILTER_K 0.15
|
||||||
@@ -14,16 +11,12 @@
|
|||||||
#define CONFIG_URL "http://%s/"
|
#define CONFIG_URL "http://%s/"
|
||||||
#define SETTINGS_VALID_VALUE "stvalid" // only 8 chars!
|
#define SETTINGS_VALID_VALUE "stvalid" // only 8 chars!
|
||||||
|
|
||||||
|
#define GPIO_IS_NOT_CONFIGURED 0xff
|
||||||
#define DEFAULT_HEATING_MIN_TEMP 20
|
#define DEFAULT_HEATING_MIN_TEMP 20
|
||||||
#define DEFAULT_HEATING_MAX_TEMP 90
|
#define DEFAULT_HEATING_MAX_TEMP 90
|
||||||
#define DEFAULT_DHW_MIN_TEMP 30
|
#define DEFAULT_DHW_MIN_TEMP 30
|
||||||
#define DEFAULT_DHW_MAX_TEMP 60
|
#define DEFAULT_DHW_MAX_TEMP 60
|
||||||
|
|
||||||
|
|
||||||
#ifndef WM_DEBUG_MODE
|
|
||||||
#define WM_DEBUG_MODE WM_DEBUG_NOTIFY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef USE_SERIAL
|
#ifndef USE_SERIAL
|
||||||
#define USE_SERIAL true
|
#define USE_SERIAL true
|
||||||
#endif
|
#endif
|
||||||
@@ -36,80 +29,93 @@
|
|||||||
#define USE_BLE false
|
#define USE_BLE false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HOSTNAME_DEFAULT
|
#ifndef DEFAULT_HOSTNAME
|
||||||
#define HOSTNAME_DEFAULT "opentherm"
|
#define DEFAULT_HOSTNAME "opentherm"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef AP_SSID_DEFAULT
|
#ifndef DEFAULT_AP_SSID
|
||||||
#define AP_SSID_DEFAULT "OpenTherm Gateway"
|
#define DEFAULT_AP_SSID "OpenTherm Gateway"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef AP_PASSWORD_DEFAULT
|
#ifndef DEFAULT_AP_PASSWORD
|
||||||
#define AP_PASSWORD_DEFAULT "otgateway123456"
|
#define DEFAULT_AP_PASSWORD "otgateway123456"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STA_SSID_DEFAULT
|
#ifndef DEFAULT_STA_SSID
|
||||||
#define STA_SSID_DEFAULT ""
|
#define DEFAULT_STA_SSID ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STA_PASSWORD_DEFAULT
|
#ifndef DEFAULT_STA_PASSWORD
|
||||||
#define STA_PASSWORD_DEFAULT ""
|
#define DEFAULT_STA_PASSWORD ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DEBUG_BY_DEFAULT
|
#ifndef DEBUG_BY_DEFAULT
|
||||||
#define DEBUG_BY_DEFAULT false
|
#define DEBUG_BY_DEFAULT false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PORTAL_LOGIN_DEFAULT
|
#ifndef DEFAULT_PORTAL_LOGIN
|
||||||
#define PORTAL_LOGIN_DEFAULT ""
|
#define DEFAULT_PORTAL_LOGIN ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PORTAL_PASSWORD_DEFAULT
|
#ifndef DEFAULT_PORTAL_PASSWORD
|
||||||
#define PORTAL_PASSWORD_DEFAULT ""
|
#define DEFAULT_PORTAL_PASSWORD ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MQTT_SERVER_DEFAULT
|
#ifndef DEFAULT_MQTT_SERVER
|
||||||
#define MQTT_SERVER_DEFAULT ""
|
#define DEFAULT_MQTT_SERVER ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MQTT_PORT_DEFAULT
|
#ifndef DEFAULT_MQTT_PORT
|
||||||
#define MQTT_PORT_DEFAULT 1883
|
#define DEFAULT_MQTT_PORT 1883
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MQTT_USER_DEFAULT
|
#ifndef DEFAULT_MQTT_USER
|
||||||
#define MQTT_USER_DEFAULT ""
|
#define DEFAULT_MQTT_USER ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MQTT_PASSWORD_DEFAULT
|
#ifndef DEFAULT_MQTT_PASSWORD
|
||||||
#define MQTT_PASSWORD_DEFAULT ""
|
#define DEFAULT_MQTT_PASSWORD ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MQTT_PREFIX_DEFAULT
|
#ifndef DEFAULT_MQTT_PREFIX
|
||||||
#define MQTT_PREFIX_DEFAULT "opentherm"
|
#define DEFAULT_MQTT_PREFIX "opentherm"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef OT_IN_PIN_DEFAULT
|
#ifndef DEFAULT_OT_IN_GPIO
|
||||||
#define OT_IN_PIN_DEFAULT 0
|
#define DEFAULT_OT_IN_GPIO GPIO_IS_NOT_CONFIGURED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef OT_OUT_PIN_DEFAULT
|
#ifndef DEFAULT_OT_OUT_GPIO
|
||||||
#define OT_OUT_PIN_DEFAULT 0
|
#define DEFAULT_OT_OUT_GPIO GPIO_IS_NOT_CONFIGURED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SENSOR_OUTDOOR_PIN_DEFAULT
|
#ifndef DEFAULT_SENSOR_OUTDOOR_GPIO
|
||||||
#define SENSOR_OUTDOOR_PIN_DEFAULT 0
|
#define DEFAULT_SENSOR_OUTDOOR_GPIO GPIO_IS_NOT_CONFIGURED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SENSOR_INDOOR_PIN_DEFAULT
|
#ifndef DEFAULT_SENSOR_INDOOR_GPIO
|
||||||
#define SENSOR_INDOOR_PIN_DEFAULT 0
|
#define DEFAULT_SENSOR_INDOOR_GPIO GPIO_IS_NOT_CONFIGURED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EXT_PUMP_PIN_DEFAULT
|
#ifndef DEFAULT_EXT_PUMP_GPIO
|
||||||
#define EXT_PUMP_PIN_DEFAULT 0
|
#define DEFAULT_EXT_PUMP_GPIO GPIO_IS_NOT_CONFIGURED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PROGMEM
|
#ifndef PROGMEM
|
||||||
#define PROGMEM
|
#define PROGMEM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef GPIO_IS_VALID_GPIO
|
||||||
|
#define GPIO_IS_VALID_GPIO(gpioNum) (gpioNum >= 0 && gpioNum <= 16)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GPIO_IS_VALID(gpioNum) (gpioNum != GPIO_IS_NOT_CONFIGURED && GPIO_IS_VALID_GPIO(gpioNum))
|
||||||
|
|
||||||
|
enum class SensorType : byte {
|
||||||
|
BOILER,
|
||||||
|
MANUAL,
|
||||||
|
DS18B20,
|
||||||
|
BLUETOOTH
|
||||||
|
};
|
||||||
|
|
||||||
char buffer[255];
|
char buffer[255];
|
||||||
@@ -143,7 +143,7 @@ void setup() {
|
|||||||
tMqtt = new MqttTask(false, 500);
|
tMqtt = new MqttTask(false, 500);
|
||||||
Scheduler.start(tMqtt);
|
Scheduler.start(tMqtt);
|
||||||
|
|
||||||
tOt = new OpenThermTask(false, 750);
|
tOt = new OpenThermTask(true, 750);
|
||||||
Scheduler.start(tOt);
|
Scheduler.start(tOt);
|
||||||
|
|
||||||
tSensors = new SensorsTask(true, EXT_SENSORS_INTERVAL);
|
tSensors = new SensorsTask(true, EXT_SENSORS_INTERVAL);
|
||||||
|
|||||||
160
src/utils.h
160
src/utils.h
@@ -273,8 +273,8 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
|
|||||||
dst["portal"]["login"] = src.portal.login;
|
dst["portal"]["login"] = src.portal.login;
|
||||||
dst["portal"]["password"] = src.portal.password;
|
dst["portal"]["password"] = src.portal.password;
|
||||||
|
|
||||||
dst["opentherm"]["inPin"] = src.opentherm.inPin;
|
dst["opentherm"]["inGpio"] = src.opentherm.inGpio;
|
||||||
dst["opentherm"]["outPin"] = src.opentherm.outPin;
|
dst["opentherm"]["outGpio"] = src.opentherm.outGpio;
|
||||||
dst["opentherm"]["memberIdCode"] = src.opentherm.memberIdCode;
|
dst["opentherm"]["memberIdCode"] = src.opentherm.memberIdCode;
|
||||||
dst["opentherm"]["dhwPresent"] = src.opentherm.dhwPresent;
|
dst["opentherm"]["dhwPresent"] = src.opentherm.dhwPresent;
|
||||||
dst["opentherm"]["summerWinterMode"] = src.opentherm.summerWinterMode;
|
dst["opentherm"]["summerWinterMode"] = src.opentherm.summerWinterMode;
|
||||||
@@ -323,12 +323,12 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
|
|||||||
dst["equitherm"]["k_factor"] = roundd(src.equitherm.k_factor, 3);
|
dst["equitherm"]["k_factor"] = roundd(src.equitherm.k_factor, 3);
|
||||||
dst["equitherm"]["t_factor"] = roundd(src.equitherm.t_factor, 3);
|
dst["equitherm"]["t_factor"] = roundd(src.equitherm.t_factor, 3);
|
||||||
|
|
||||||
dst["sensors"]["outdoor"]["type"] = src.sensors.outdoor.type;
|
dst["sensors"]["outdoor"]["type"] = static_cast<byte>(src.sensors.outdoor.type);
|
||||||
dst["sensors"]["outdoor"]["pin"] = src.sensors.outdoor.pin;
|
dst["sensors"]["outdoor"]["gpio"] = src.sensors.outdoor.gpio;
|
||||||
dst["sensors"]["outdoor"]["offset"] = roundd(src.sensors.outdoor.offset, 2);
|
dst["sensors"]["outdoor"]["offset"] = roundd(src.sensors.outdoor.offset, 2);
|
||||||
|
|
||||||
dst["sensors"]["indoor"]["type"] = src.sensors.indoor.type;
|
dst["sensors"]["indoor"]["type"] = static_cast<byte>(src.sensors.indoor.type);
|
||||||
dst["sensors"]["indoor"]["pin"] = src.sensors.indoor.pin;
|
dst["sensors"]["indoor"]["gpio"] = src.sensors.indoor.gpio;
|
||||||
|
|
||||||
char bleAddress[18];
|
char bleAddress[18];
|
||||||
sprintf(
|
sprintf(
|
||||||
@@ -346,7 +346,7 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
|
|||||||
|
|
||||||
if (!safe) {
|
if (!safe) {
|
||||||
dst["externalPump"]["use"] = src.externalPump.use;
|
dst["externalPump"]["use"] = src.externalPump.use;
|
||||||
dst["externalPump"]["pin"] = src.externalPump.pin;
|
dst["externalPump"]["gpio"] = src.externalPump.gpio;
|
||||||
dst["externalPump"]["postCirculationTime"] = roundd(src.externalPump.postCirculationTime / 60, 0);
|
dst["externalPump"]["postCirculationTime"] = roundd(src.externalPump.postCirculationTime / 60, 0);
|
||||||
dst["externalPump"]["antiStuckInterval"] = roundd(src.externalPump.antiStuckInterval / 86400, 0);
|
dst["externalPump"]["antiStuckInterval"] = roundd(src.externalPump.antiStuckInterval / 86400, 0);
|
||||||
dst["externalPump"]["antiStuckTime"] = roundd(src.externalPump.antiStuckTime / 60, 0);
|
dst["externalPump"]["antiStuckTime"] = roundd(src.externalPump.antiStuckTime / 60, 0);
|
||||||
@@ -404,22 +404,38 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
|||||||
|
|
||||||
|
|
||||||
// opentherm
|
// opentherm
|
||||||
if (!src["opentherm"]["inPin"].isNull()) {
|
if (!src["opentherm"]["inGpio"].isNull()) {
|
||||||
unsigned char value = src["opentherm"]["inPin"].as<unsigned char>();
|
if (src["opentherm"]["inGpio"].is<JsonString>() && src["opentherm"]["inGpio"].as<JsonString>().size() == 0) {
|
||||||
|
if (dst.opentherm.inGpio != GPIO_IS_NOT_CONFIGURED) {
|
||||||
|
dst.opentherm.inGpio = GPIO_IS_NOT_CONFIGURED;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (value >= 0 && value < 50) {
|
} else {
|
||||||
dst.opentherm.inPin = value;
|
unsigned char value = src["opentherm"]["inGpio"].as<unsigned char>();
|
||||||
|
|
||||||
|
if (value >= 0 && value <= 254) {
|
||||||
|
dst.opentherm.inGpio = value;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!src["opentherm"]["outPin"].isNull()) {
|
if (!src["opentherm"]["outGpio"].isNull()) {
|
||||||
unsigned char value = src["opentherm"]["outPin"].as<unsigned char>();
|
if (src["opentherm"]["outGpio"].is<JsonString>() && src["opentherm"]["outGpio"].as<JsonString>().size() == 0) {
|
||||||
|
if (dst.opentherm.outGpio != GPIO_IS_NOT_CONFIGURED) {
|
||||||
if (value >= 0 && value < 50) {
|
dst.opentherm.outGpio = GPIO_IS_NOT_CONFIGURED;
|
||||||
dst.opentherm.outPin = value;
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
unsigned char value = src["opentherm"]["outGpio"].as<unsigned char>();
|
||||||
|
|
||||||
|
if (value >= 0 && value <= 254) {
|
||||||
|
dst.opentherm.outGpio = value;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!src["opentherm"]["memberIdCode"].isNull()) {
|
if (!src["opentherm"]["memberIdCode"].isNull()) {
|
||||||
@@ -558,7 +574,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (src["emergency"]["useEquitherm"].is<bool>()) {
|
if (src["emergency"]["useEquitherm"].is<bool>()) {
|
||||||
if (dst.sensors.outdoor.type != 1) {
|
if (dst.sensors.outdoor.type != SensorType::MANUAL) {
|
||||||
dst.emergency.useEquitherm = src["emergency"]["useEquitherm"].as<bool>();
|
dst.emergency.useEquitherm = src["emergency"]["useEquitherm"].as<bool>();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -573,7 +589,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (src["emergency"]["usePid"].is<bool>()) {
|
if (src["emergency"]["usePid"].is<bool>()) {
|
||||||
if (dst.sensors.indoor.type != 1) {
|
if (dst.sensors.indoor.type != SensorType::MANUAL) {
|
||||||
dst.emergency.usePid = src["emergency"]["usePid"].as<bool>();
|
dst.emergency.usePid = src["emergency"]["usePid"].as<bool>();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -776,27 +792,46 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
|||||||
|
|
||||||
// sensors
|
// sensors
|
||||||
if (!src["sensors"]["outdoor"]["type"].isNull()) {
|
if (!src["sensors"]["outdoor"]["type"].isNull()) {
|
||||||
unsigned char value = src["sensors"]["outdoor"]["type"].as<unsigned char>();
|
byte value = src["sensors"]["outdoor"]["type"].as<unsigned char>();
|
||||||
|
|
||||||
if (value >= 0 && value <= 2) {
|
switch (value) {
|
||||||
dst.sensors.outdoor.type = value;
|
case static_cast<byte>(SensorType::BOILER):
|
||||||
|
dst.sensors.outdoor.type = SensorType::BOILER;
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
if (dst.sensors.outdoor.type == 1) {
|
case static_cast<byte>(SensorType::MANUAL):
|
||||||
|
dst.sensors.outdoor.type = SensorType::MANUAL;
|
||||||
dst.emergency.useEquitherm = false;
|
dst.emergency.useEquitherm = false;
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case static_cast<byte>(SensorType::DS18B20):
|
||||||
|
dst.sensors.outdoor.type = SensorType::DS18B20;
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!src["sensors"]["outdoor"]["gpio"].isNull()) {
|
||||||
|
if (src["sensors"]["outdoor"]["gpio"].is<JsonString>() && src["sensors"]["outdoor"]["gpio"].as<JsonString>().size() == 0) {
|
||||||
|
if (dst.sensors.outdoor.gpio != GPIO_IS_NOT_CONFIGURED) {
|
||||||
|
dst.sensors.outdoor.gpio = GPIO_IS_NOT_CONFIGURED;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!src["sensors"]["outdoor"]["pin"].isNull()) {
|
} else {
|
||||||
unsigned char value = src["sensors"]["outdoor"]["pin"].as<unsigned char>();
|
unsigned char value = src["sensors"]["outdoor"]["gpio"].as<unsigned char>();
|
||||||
|
|
||||||
if (value >= 0 && value <= 50) {
|
if (value >= 0 && value <= 254) {
|
||||||
dst.sensors.outdoor.pin = value;
|
dst.sensors.outdoor.gpio = value;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!src["sensors"]["outdoor"]["offset"].isNull()) {
|
if (!src["sensors"]["outdoor"]["offset"].isNull()) {
|
||||||
double value = src["sensors"]["outdoor"]["offset"].as<double>();
|
double value = src["sensors"]["outdoor"]["offset"].as<double>();
|
||||||
@@ -808,27 +843,54 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!src["sensors"]["indoor"]["type"].isNull()) {
|
if (!src["sensors"]["indoor"]["type"].isNull()) {
|
||||||
unsigned char value = src["sensors"]["indoor"]["type"].as<unsigned char>();
|
byte value = src["sensors"]["indoor"]["type"].as<unsigned char>();
|
||||||
|
|
||||||
if (value >= 1 && value <= 3) {
|
|
||||||
dst.sensors.indoor.type = value;
|
|
||||||
|
|
||||||
if (dst.sensors.indoor.type == 1) {
|
switch (value) {
|
||||||
dst.emergency.usePid = false;
|
case static_cast<byte>(SensorType::BOILER):
|
||||||
|
dst.sensors.indoor.type = SensorType::BOILER;
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case static_cast<byte>(SensorType::MANUAL):
|
||||||
|
dst.sensors.indoor.type = SensorType::MANUAL;
|
||||||
|
dst.emergency.useEquitherm = false;
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case static_cast<byte>(SensorType::DS18B20):
|
||||||
|
dst.sensors.indoor.type = SensorType::DS18B20;
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if USE_BLE
|
||||||
|
case static_cast<byte>(SensorType::BLUETOOTH):
|
||||||
|
dst.sensors.indoor.type = SensorType::BLUETOOTH;
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!src["sensors"]["indoor"]["gpio"].isNull()) {
|
||||||
|
if (src["sensors"]["indoor"]["gpio"].is<JsonString>() && src["sensors"]["indoor"]["gpio"].as<JsonString>().size() == 0) {
|
||||||
|
if (dst.sensors.indoor.gpio != GPIO_IS_NOT_CONFIGURED) {
|
||||||
|
dst.sensors.indoor.gpio = GPIO_IS_NOT_CONFIGURED;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!src["sensors"]["indoor"]["pin"].isNull()) {
|
} else {
|
||||||
unsigned char value = src["sensors"]["indoor"]["pin"].as<unsigned char>();
|
unsigned char value = src["sensors"]["indoor"]["gpio"].as<unsigned char>();
|
||||||
|
|
||||||
if (value >= 0 && value <= 50) {
|
if (value >= 0 && value <= 254) {
|
||||||
dst.sensors.indoor.pin = value;
|
dst.sensors.indoor.gpio = value;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if USE_BLE
|
#if USE_BLE
|
||||||
if (!src["sensors"]["indoor"]["bleAddresss"].isNull()) {
|
if (!src["sensors"]["indoor"]["bleAddresss"].isNull()) {
|
||||||
@@ -861,13 +923,21 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!src["externalPump"]["pin"].isNull()) {
|
if (!src["externalPump"]["gpio"].isNull()) {
|
||||||
unsigned char value = src["externalPump"]["pin"].as<unsigned char>();
|
if (src["externalPump"]["gpio"].is<JsonString>() && src["externalPump"]["gpio"].as<JsonString>().size() == 0) {
|
||||||
|
if (dst.externalPump.gpio != GPIO_IS_NOT_CONFIGURED) {
|
||||||
if (value >= 0 && value <= 50) {
|
dst.externalPump.gpio = GPIO_IS_NOT_CONFIGURED;
|
||||||
dst.externalPump.pin = value;
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
unsigned char value = src["externalPump"]["gpio"].as<unsigned char>();
|
||||||
|
|
||||||
|
if (value >= 0 && value <= 254) {
|
||||||
|
dst.externalPump.gpio = value;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!src["externalPump"]["postCirculationTime"].isNull()) {
|
if (!src["externalPump"]["postCirculationTime"].isNull()) {
|
||||||
@@ -928,7 +998,9 @@ void varsToJson(const Variables& src, JsonVariant dst) {
|
|||||||
dst["temperatures"]["indoor"] = roundd(src.temperatures.indoor, 2);
|
dst["temperatures"]["indoor"] = roundd(src.temperatures.indoor, 2);
|
||||||
dst["temperatures"]["outdoor"] = roundd(src.temperatures.outdoor, 2);
|
dst["temperatures"]["outdoor"] = roundd(src.temperatures.outdoor, 2);
|
||||||
dst["temperatures"]["heating"] = roundd(src.temperatures.heating, 2);
|
dst["temperatures"]["heating"] = roundd(src.temperatures.heating, 2);
|
||||||
|
dst["temperatures"]["heatingReturn"] = roundd(src.temperatures.heatingReturn, 2);
|
||||||
dst["temperatures"]["dhw"] = roundd(src.temperatures.dhw, 2);
|
dst["temperatures"]["dhw"] = roundd(src.temperatures.dhw, 2);
|
||||||
|
dst["temperatures"]["exhaust"] = roundd(src.temperatures.exhaust, 2);
|
||||||
|
|
||||||
dst["parameters"]["heatingEnabled"] = src.parameters.heatingEnabled;
|
dst["parameters"]["heatingEnabled"] = src.parameters.heatingEnabled;
|
||||||
dst["parameters"]["heatingMinTemp"] = src.parameters.heatingMinTemp;
|
dst["parameters"]["heatingMinTemp"] = src.parameters.heatingMinTemp;
|
||||||
@@ -961,7 +1033,7 @@ bool jsonToVars(const JsonVariantConst src, Variables& dst) {
|
|||||||
if (!src["temperatures"]["indoor"].isNull()) {
|
if (!src["temperatures"]["indoor"].isNull()) {
|
||||||
double value = src["temperatures"]["indoor"].as<double>();
|
double value = src["temperatures"]["indoor"].as<double>();
|
||||||
|
|
||||||
if (settings.sensors.indoor.type == 1 && value > -100 && value < 100) {
|
if (settings.sensors.indoor.type == SensorType::MANUAL && value > -100 && value < 100) {
|
||||||
dst.temperatures.indoor = roundd(value, 2);
|
dst.temperatures.indoor = roundd(value, 2);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
@@ -970,7 +1042,7 @@ bool jsonToVars(const JsonVariantConst src, Variables& dst) {
|
|||||||
if (!src["temperatures"]["outdoor"].isNull()) {
|
if (!src["temperatures"]["outdoor"].isNull()) {
|
||||||
double value = src["temperatures"]["outdoor"].as<double>();
|
double value = src["temperatures"]["outdoor"].as<double>();
|
||||||
|
|
||||||
if (settings.sensors.outdoor.type == 1 && value > -100 && value < 100) {
|
if (settings.sensors.outdoor.type == SensorType::MANUAL && value > -100 && value < 100) {
|
||||||
dst.temperatures.outdoor = roundd(value, 2);
|
dst.temperatures.outdoor = roundd(value, 2);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -491,8 +491,8 @@ async function loadSettings() {
|
|||||||
setInputValue('.portal-password', result.portal.password);
|
setInputValue('.portal-password', result.portal.password);
|
||||||
setBusy('#portal-settings-busy', '#portal-settings', false);
|
setBusy('#portal-settings-busy', '#portal-settings', false);
|
||||||
|
|
||||||
setInputValue('.opentherm-in-pin', result.opentherm.inPin);
|
setInputValue('.opentherm-in-gpio', result.opentherm.inGpio < 255 ? result.opentherm.inGpio : '');
|
||||||
setInputValue('.opentherm-out-pin', result.opentherm.outPin);
|
setInputValue('.opentherm-out-gpio', result.opentherm.outGpio < 255 ? result.opentherm.outGpio : '');
|
||||||
setInputValue('.opentherm-member-id-code', result.opentherm.memberIdCode);
|
setInputValue('.opentherm-member-id-code', result.opentherm.memberIdCode);
|
||||||
setCheckboxValue('.opentherm-dhw-present', result.opentherm.dhwPresent);
|
setCheckboxValue('.opentherm-dhw-present', result.opentherm.dhwPresent);
|
||||||
setCheckboxValue('.opentherm-sw-mode', result.opentherm.summerWinterMode);
|
setCheckboxValue('.opentherm-sw-mode', result.opentherm.summerWinterMode);
|
||||||
@@ -512,18 +512,18 @@ async function loadSettings() {
|
|||||||
setBusy('#mqtt-settings-busy', '#mqtt-settings', false);
|
setBusy('#mqtt-settings-busy', '#mqtt-settings', false);
|
||||||
|
|
||||||
setRadioValue('.outdoor-sensor-type', result.sensors.outdoor.type);
|
setRadioValue('.outdoor-sensor-type', result.sensors.outdoor.type);
|
||||||
setInputValue('.outdoor-sensor-pin', result.sensors.outdoor.pin);
|
setInputValue('.outdoor-sensor-gpio', result.sensors.outdoor.gpio < 255 ? result.sensors.outdoor.gpio : '');
|
||||||
setInputValue('.outdoor-sensor-offset', result.sensors.outdoor.offset);
|
setInputValue('.outdoor-sensor-offset', result.sensors.outdoor.offset);
|
||||||
setBusy('#outdoor-sensor-settings-busy', '#outdoor-sensor-settings', false);
|
setBusy('#outdoor-sensor-settings-busy', '#outdoor-sensor-settings', false);
|
||||||
|
|
||||||
setRadioValue('.indoor-sensor-type', result.sensors.indoor.type);
|
setRadioValue('.indoor-sensor-type', result.sensors.indoor.type);
|
||||||
setInputValue('.indoor-sensor-pin', result.sensors.indoor.pin);
|
setInputValue('.indoor-sensor-gpio', result.sensors.indoor.gpio < 255 ? result.sensors.indoor.gpio : '');
|
||||||
setInputValue('.indoor-sensor-offset', result.sensors.indoor.offset);
|
setInputValue('.indoor-sensor-offset', result.sensors.indoor.offset);
|
||||||
setInputValue('.indoor-sensor-ble-addresss', result.sensors.indoor.bleAddresss);
|
setInputValue('.indoor-sensor-ble-addresss', result.sensors.indoor.bleAddresss);
|
||||||
setBusy('#indoor-sensor-settings-busy', '#indoor-sensor-settings', false);
|
setBusy('#indoor-sensor-settings-busy', '#indoor-sensor-settings', false);
|
||||||
|
|
||||||
setCheckboxValue('.extpump-use', result.externalPump.use);
|
setCheckboxValue('.extpump-use', result.externalPump.use);
|
||||||
setInputValue('.extpump-pin', result.externalPump.pin);
|
setInputValue('.extpump-gpio', result.externalPump.gpio < 255 ? result.externalPump.gpio : '');
|
||||||
setInputValue('.extpump-pc-time', result.externalPump.postCirculationTime);
|
setInputValue('.extpump-pc-time', result.externalPump.postCirculationTime);
|
||||||
setInputValue('.extpump-as-interval', result.externalPump.antiStuckInterval);
|
setInputValue('.extpump-as-interval', result.externalPump.antiStuckInterval);
|
||||||
setInputValue('.extpump-as-time', result.externalPump.antiStuckTime);
|
setInputValue('.extpump-as-time', result.externalPump.antiStuckTime);
|
||||||
|
|||||||
Reference in New Issue
Block a user