refactor: optimization

* names changed: pin => gpio
* ability to change OpenTherm GPIO without rebooting
This commit is contained in:
Yurii
2024-03-10 04:10:18 +03:00
parent 07ab121788
commit b07dd46f55
12 changed files with 388 additions and 310 deletions

View File

@@ -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>

Binary file not shown.

View File

@@ -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;

View File

@@ -17,7 +17,7 @@ framework = arduino
lib_deps = lib_deps =
bblanchon/ArduinoJson@^7.0.3 bblanchon/ArduinoJson@^7.0.3
;ihormelnyk/OpenTherm Library@^1.1.5 ;ihormelnyk/OpenTherm Library@^1.1.5
https://github.com/ihormelnyk/opentherm_library.git?080324 https://github.com/ihormelnyk/opentherm_library.git
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
@@ -34,18 +34,18 @@ build_flags =
-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
@@ -67,7 +67,7 @@ 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 +91,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 +107,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 +123,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 +139,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 +158,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 +179,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 +198,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 +218,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

View File

@@ -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"));
} }

View File

@@ -1,27 +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);
~OpenThermTask() {
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,9 +44,35 @@ protected:
} }
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"),
@@ -48,68 +82,39 @@ protected:
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->begin(); this->instance->begin();
#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;
@@ -118,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,
@@ -128,20 +133,20 @@ protected:
settings.opentherm.dhwBlocking settings.opentherm.dhwBlocking
); );
if (!CustomOpenTherm::isValidResponse(localResponse)) { if (!CustomOpenTherm::isValidResponse(response)) {
Log.swarningln(FPSTR(L_OT), F("Invalid response after setBoilerStatus: %s"), CustomOpenTherm::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
@@ -155,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 = CustomOpenTherm::isCentralHeatingActive(localResponse); vars.states.heating = CustomOpenTherm::isCentralHeatingActive(response);
vars.states.dhw = settings.opentherm.dhwPresent ? CustomOpenTherm::isHotWaterActive(localResponse) : false; vars.states.dhw = settings.opentherm.dhwPresent ? CustomOpenTherm::isHotWaterActive(response) : false;
vars.states.flame = CustomOpenTherm::isFlameOn(localResponse); vars.states.flame = CustomOpenTherm::isFlameOn(response);
vars.states.fault = CustomOpenTherm::isFault(localResponse); vars.states.fault = CustomOpenTherm::isFault(response);
vars.states.diagnostic = CustomOpenTherm::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) {
@@ -282,7 +297,7 @@ protected:
// 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 {
@@ -296,7 +311,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 {
@@ -318,7 +333,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();
@@ -328,7 +343,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"));
} }
} }
@@ -340,7 +355,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)) {
currentHeatingTemp = vars.parameters.heatingSetpoint; currentHeatingTemp = vars.parameters.heatingSetpoint;
this->heatingSetTempTime = millis(); this->heatingSetTempTime = millis();
@@ -350,7 +365,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"));
} }
} }
@@ -373,8 +388,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() {
@@ -386,7 +433,7 @@ protected:
} }
bool updateSlaveConfig() { bool updateSlaveConfig() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::READ_DATA, OpenThermRequestType::READ_DATA,
OpenThermMessageID::SConfigSMemberIDcode, OpenThermMessageID::SConfigSMemberIDcode,
0 0
@@ -447,7 +494,7 @@ protected:
return true; return true;
} }
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::WRITE_DATA, OpenThermRequestType::WRITE_DATA,
OpenThermMessageID::MConfigMMemberIDcode, OpenThermMessageID::MConfigMMemberIDcode,
request request
@@ -457,22 +504,22 @@ protected:
} }
bool setMaxModulationLevel(byte value) { bool setMaxModulationLevel(byte value) {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::WRITE_DATA, OpenThermRequestType::WRITE_DATA,
OpenThermMessageID::MaxRelModLevelSetting, OpenThermMessageID::MaxRelModLevelSetting,
ot->toF88(value) this->instance->toF88(value)
)); ));
if (!CustomOpenTherm::isValidResponse(response)) { if (!CustomOpenTherm::isValidResponse(response)) {
return false; return false;
} }
vars.parameters.maxModulation = ot->fromF88(response); vars.parameters.maxModulation = this->instance->fromF88(response);
return true; return true;
} }
bool updateSlaveOtVersion() { bool updateSlaveOtVersion() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::READ_DATA, OpenThermRequestType::READ_DATA,
OpenThermMessageID::OpenThermVersionSlave, OpenThermMessageID::OpenThermVersionSlave,
0 0
@@ -487,23 +534,23 @@ protected:
} }
bool setMasterOtVersion(float version) { bool setMasterOtVersion(float version) {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::WRITE_DATA, OpenThermRequestType::WRITE_DATA,
OpenThermMessageID::OpenThermVersionMaster, OpenThermMessageID::OpenThermVersionMaster,
ot->toF88(version) this->instance->toF88(version)
)); ));
if (!CustomOpenTherm::isValidResponse(response)) { if (!CustomOpenTherm::isValidResponse(response)) {
return false; return false;
} }
vars.parameters.masterOtVersion = ot->fromF88(response); vars.parameters.masterOtVersion = this->instance->fromF88(response);
return true; return true;
} }
bool updateSlaveVersion() { bool updateSlaveVersion() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::READ_DATA, OpenThermRequestType::READ_DATA,
OpenThermMessageID::SlaveVersion, OpenThermMessageID::SlaveVersion,
0 0
@@ -520,7 +567,7 @@ protected:
} }
bool setMasterVersion(uint8_t version, uint8_t type) { bool setMasterVersion(uint8_t version, uint8_t type) {
unsigned long response = ot->sendRequest(CustomOpenTherm::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
@@ -537,7 +584,7 @@ protected:
} }
bool updateMinMaxDhwTemp() { bool updateMinMaxDhwTemp() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::READ_DATA, OpenThermRequestType::READ_DATA,
OpenThermMessageID::TdhwSetUBTdhwSetLB, OpenThermMessageID::TdhwSetUBTdhwSetLB,
0 0
@@ -561,7 +608,7 @@ protected:
} }
bool updateMinMaxHeatingTemp() { bool updateMinMaxHeatingTemp() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::READ_DATA, OpenThermRequestType::READ_DATA,
OpenThermMessageID::MaxTSetUBMaxTSetLB, OpenThermMessageID::MaxTSetUBMaxTSetLB,
0 0
@@ -584,7 +631,7 @@ protected:
} }
bool setMaxHeatingTemp(byte value) { bool setMaxHeatingTemp(byte value) {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermMessageType::WRITE_DATA, OpenThermMessageType::WRITE_DATA,
OpenThermMessageID::MaxTSet, OpenThermMessageID::MaxTSet,
CustomOpenTherm::temperatureToData(value) CustomOpenTherm::temperatureToData(value)
@@ -594,7 +641,7 @@ protected:
} }
bool updateOutsideTemp() { bool updateOutsideTemp() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::READ_DATA, OpenThermRequestType::READ_DATA,
OpenThermMessageID::Toutside, OpenThermMessageID::Toutside,
0 0
@@ -609,7 +656,7 @@ protected:
} }
bool updateHeatingTemp() { bool updateHeatingTemp() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermMessageType::READ_DATA, OpenThermMessageType::READ_DATA,
OpenThermMessageID::Tboiler, OpenThermMessageID::Tboiler,
0 0
@@ -630,7 +677,7 @@ protected:
bool updateDhwTemp() { bool updateDhwTemp() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermMessageType::READ_DATA, OpenThermMessageType::READ_DATA,
OpenThermMessageID::Tdhw, OpenThermMessageID::Tdhw,
0 0
@@ -650,7 +697,7 @@ protected:
} }
bool updateDhwFlowRate() { bool updateDhwFlowRate() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermMessageType::READ_DATA, OpenThermMessageType::READ_DATA,
OpenThermMessageID::DHWFlowRate, OpenThermMessageID::DHWFlowRate,
0 0
@@ -670,7 +717,7 @@ protected:
} }
bool updateFaultCode() { bool updateFaultCode() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::READ_DATA, OpenThermRequestType::READ_DATA,
OpenThermMessageID::ASFflags, OpenThermMessageID::ASFflags,
0 0
@@ -685,7 +732,7 @@ protected:
} }
bool updateModulationLevel() { bool updateModulationLevel() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::READ_DATA, OpenThermRequestType::READ_DATA,
OpenThermMessageID::RelModLevel, OpenThermMessageID::RelModLevel,
0 0
@@ -695,7 +742,7 @@ protected:
return false; return false;
} }
float modulation = ot->fromF88(response); float modulation = this->instance->fromF88(response);
if (!vars.states.flame) { if (!vars.states.flame) {
vars.sensors.modulation = 0; vars.sensors.modulation = 0;
} else { } else {
@@ -706,7 +753,7 @@ protected:
} }
bool updatePressure() { bool updatePressure() {
unsigned long response = ot->sendRequest(CustomOpenTherm::buildRequest( unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::READ_DATA, OpenThermRequestType::READ_DATA,
OpenThermMessageID::CHPressure, OpenThermMessageID::CHPressure,
0 0

View File

@@ -60,39 +60,38 @@ protected:
} }
void loop() { void loop() {
bool needUpdateIndoorTemp = false; bool indoorTempUpdated = false;
bool needUpdateOutdoorTemp = false; bool outdoorTempUpdated = false;
if (settings.sensors.outdoor.type == 2 && settings.sensors.outdoor.pin) { if (settings.sensors.outdoor.type == 2 && GPIO_IS_VALID(settings.sensors.indoor.gpio)) {
outdoorTemperatureSensor(); outdoorTemperatureSensor();
needUpdateOutdoorTemp = true; outdoorTempUpdated = true;
} }
if (settings.sensors.indoor.type == 2 && settings.sensors.indoor.pin) { if (settings.sensors.indoor.type == 2 && GPIO_IS_VALID(settings.sensors.indoor.gpio)) {
indoorTemperatureSensor(); indoorTemperatureSensor();
needUpdateIndoorTemp = true; indoorTempUpdated = true;
} }
#if USE_BLE #if USE_BLE
if (settings.sensors.indoor.type == 3) { else if (settings.sensors.indoor.type == 3) {
bluetoothSensor(); indoorTemperatureBluetoothSensor();
needUpdateIndoorTemp = true; indoorTempUpdated = true;
} }
#endif #endif
if (needUpdateOutdoorTemp && 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 (needUpdateIndoorTemp && 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"));
@@ -210,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(
@@ -276,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(

View File

@@ -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;
@@ -102,14 +102,14 @@ struct Settings {
struct { struct {
// 0 - boiler, 1 - manual, 2 - ds18b20 // 0 - boiler, 1 - manual, 2 - ds18b20
byte type = 0; byte type = 0;
byte pin = SENSOR_OUTDOOR_PIN_DEFAULT; byte gpio = DEFAULT_SENSOR_OUTDOOR_GPIO;
float offset = 0.0f; float offset = 0.0f;
} outdoor; } outdoor;
struct { struct {
// 1 - manual, 2 - ds18b20, 3 - ble // 1 - manual, 2 - ds18b20, 3 - ble
byte type = 1; byte type = 1;
byte pin = SENSOR_INDOOR_PIN_DEFAULT; byte gpio = DEFAULT_SENSOR_INDOOR_GPIO;
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 +117,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;

View File

@@ -4,9 +4,6 @@
#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,86 @@
#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))
char buffer[255]; char buffer[255];

View File

@@ -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);

View File

@@ -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;
@@ -324,11 +324,11 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
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"] = 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"] = 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()) {
@@ -789,13 +805,21 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
} }
} }
if (!src["sensors"]["outdoor"]["pin"].isNull()) { if (!src["sensors"]["outdoor"]["gpio"].isNull()) {
unsigned char value = src["sensors"]["outdoor"]["pin"].as<unsigned char>(); if (src["sensors"]["outdoor"]["gpio"].is<JsonString>() && src["sensors"]["outdoor"]["gpio"].as<JsonString>().size() == 0) {
if (dst.sensors.outdoor.gpio != GPIO_IS_NOT_CONFIGURED) {
if (value >= 0 && value <= 50) { dst.sensors.outdoor.gpio = GPIO_IS_NOT_CONFIGURED;
dst.sensors.outdoor.pin = value;
changed = true; changed = true;
} }
} else {
unsigned char value = src["sensors"]["outdoor"]["gpio"].as<unsigned char>();
if (value >= 0 && value <= 254) {
dst.sensors.outdoor.gpio = value;
changed = true;
}
}
} }
if (!src["sensors"]["outdoor"]["offset"].isNull()) { if (!src["sensors"]["outdoor"]["offset"].isNull()) {
@@ -821,13 +845,21 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
} }
} }
if (!src["sensors"]["indoor"]["pin"].isNull()) { if (!src["sensors"]["indoor"]["gpio"].isNull()) {
unsigned char value = src["sensors"]["indoor"]["pin"].as<unsigned char>(); if (src["sensors"]["indoor"]["gpio"].is<JsonString>() && src["sensors"]["indoor"]["gpio"].as<JsonString>().size() == 0) {
if (dst.sensors.indoor.gpio != GPIO_IS_NOT_CONFIGURED) {
if (value >= 0 && value <= 50) { dst.sensors.indoor.gpio = GPIO_IS_NOT_CONFIGURED;
dst.sensors.indoor.pin = value;
changed = true; changed = true;
} }
} else {
unsigned char value = src["sensors"]["indoor"]["gpio"].as<unsigned char>();
if (value >= 0 && value <= 254) {
dst.sensors.indoor.gpio = value;
changed = true;
}
}
} }
#if USE_BLE #if USE_BLE
@@ -861,13 +893,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()) {

View File

@@ -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);