* Added new OT parameters
* Improved compatibility with the boiler ITALTHERM TIME MAX 30F
* Refactoring min/max temp
* Fix port forwarding: disable captive portal after connecting to wifi
* Compatible with WOKWI emulator
* upd README
This commit is contained in:
Yurii
2023-11-17 21:47:33 +03:00
parent 9f24efb0ab
commit 7c5810e6d1
9 changed files with 161 additions and 44 deletions

View File

@@ -38,6 +38,7 @@
| [Ferroli DOMIcompact C 24](https://github.com/Laxilef/OTGateway/issues/3#issuecomment-1765310058)<br><sub>Board: MF08FA</sub> | 211 | Pressure sensor not supported | | [Ferroli DOMIcompact C 24](https://github.com/Laxilef/OTGateway/issues/3#issuecomment-1765310058)<br><sub>Board: MF08FA</sub> | 211 | Pressure sensor not supported |
| [Thermet Ecocondens Silver 35kW](https://github.com/Laxilef/OTGateway/issues/3#issuecomment-1767026384) | default | Pressure sensor not supported | | [Thermet Ecocondens Silver 35kW](https://github.com/Laxilef/OTGateway/issues/3#issuecomment-1767026384) | default | Pressure sensor not supported |
| [BAXI LUNA-3](https://github.com/Laxilef/OTGateway/issues/3#issuecomment-1794187178) | default | - | | [BAXI LUNA-3](https://github.com/Laxilef/OTGateway/issues/3#issuecomment-1794187178) | default | - |
| ITALTHERM TIME MAX 30F | default | Pressure sensor not supported<br>**Important:** on the "setup" page you need to set the checkbox "Opentherm summer/winter mode" |
## PCB ## PCB

View File

@@ -65,6 +65,7 @@ build_flags =
-D SENSOR_INDOOR_PIN_DEFAULT=14 -D SENSOR_INDOOR_PIN_DEFAULT=14
-D LED_STATUS_PIN=13 -D LED_STATUS_PIN=13
-D LED_OT_RX_PIN=15 -D LED_OT_RX_PIN=15
-D USE_TELNET=1
[env:d1_mini_lite] [env:d1_mini_lite]
platform = ${esp8266_defaults.platform} platform = ${esp8266_defaults.platform}
@@ -80,6 +81,7 @@ build_flags =
-D SENSOR_INDOOR_PIN_DEFAULT=14 -D SENSOR_INDOOR_PIN_DEFAULT=14
-D LED_STATUS_PIN=13 -D LED_STATUS_PIN=13
-D LED_OT_RX_PIN=15 -D LED_OT_RX_PIN=15
-D USE_TELNET=1
[env:d1_mini_pro] [env:d1_mini_pro]
platform = ${esp8266_defaults.platform} platform = ${esp8266_defaults.platform}
@@ -95,6 +97,7 @@ build_flags =
-D SENSOR_INDOOR_PIN_DEFAULT=14 -D SENSOR_INDOOR_PIN_DEFAULT=14
-D LED_STATUS_PIN=13 -D LED_STATUS_PIN=13
-D LED_OT_RX_PIN=15 -D LED_OT_RX_PIN=15
-D USE_TELNET=1
[env:s2_mini] [env:s2_mini]
platform = ${esp32_defaults.platform} platform = ${esp32_defaults.platform}
@@ -110,6 +113,7 @@ build_flags =
-D SENSOR_INDOOR_PIN_DEFAULT=7 -D SENSOR_INDOOR_PIN_DEFAULT=7
-D LED_STATUS_PIN=11 -D LED_STATUS_PIN=11
-D LED_OT_RX_PIN=12 -D LED_OT_RX_PIN=12
-D USE_TELNET=1
[env:s3_mini] [env:s3_mini]
platform = ${esp32_defaults.platform} platform = ${esp32_defaults.platform}
@@ -125,6 +129,7 @@ build_flags =
-D SENSOR_INDOOR_PIN_DEFAULT=12 -D SENSOR_INDOOR_PIN_DEFAULT=12
-D LED_STATUS_PIN=11 -D LED_STATUS_PIN=11
-D LED_OT_RX_PIN=10 -D LED_OT_RX_PIN=10
-D USE_TELNET=1
[env:c3_mini] [env:c3_mini]
platform = ${esp32_defaults.platform} platform = ${esp32_defaults.platform}
@@ -140,6 +145,7 @@ build_flags =
-D SENSOR_INDOOR_PIN_DEFAULT=1 -D SENSOR_INDOOR_PIN_DEFAULT=1
-D LED_STATUS_PIN=4 -D LED_STATUS_PIN=4
-D LED_OT_RX_PIN=5 -D LED_OT_RX_PIN=5
-D USE_TELNET=1
[env:nodemcu_32s] [env:nodemcu_32s]
platform = ${esp32_defaults.platform} platform = ${esp32_defaults.platform}
@@ -155,3 +161,8 @@ build_flags =
-D SENSOR_INDOOR_PIN_DEFAULT=13 -D SENSOR_INDOOR_PIN_DEFAULT=13
-D LED_STATUS_PIN=2 ; 18 -D LED_STATUS_PIN=2 ; 18
-D LED_OT_RX_PIN=19 -D LED_OT_RX_PIN=19
-D USE_TELNET=1
;-D WOKWI=1
;-D USE_TELNET=0
;-D DEBUG_BY_DEFAULT=1
;-D WM_DEBUG_MODE=3

View File

@@ -141,7 +141,6 @@ protected:
if (!doc["heating"]["maxTemp"].isNull() && doc["heating"]["maxTemp"].is<unsigned char>()) { if (!doc["heating"]["maxTemp"].isNull() && doc["heating"]["maxTemp"].is<unsigned char>()) {
if (doc["heating"]["maxTemp"].as<unsigned char>() > 0 && doc["heating"]["maxTemp"].as<unsigned char>() <= 100 && doc["heating"]["maxTemp"].as<unsigned char>() > settings.heating.minTemp) { if (doc["heating"]["maxTemp"].as<unsigned char>() > 0 && doc["heating"]["maxTemp"].as<unsigned char>() <= 100 && doc["heating"]["maxTemp"].as<unsigned char>() > settings.heating.minTemp) {
settings.heating.maxTemp = doc["heating"]["maxTemp"].as<unsigned char>(); settings.heating.maxTemp = doc["heating"]["maxTemp"].as<unsigned char>();
vars.parameters.heatingMaxTemp = settings.heating.maxTemp;
flag = true; flag = true;
} }
} }
@@ -149,7 +148,6 @@ protected:
if (!doc["heating"]["minTemp"].isNull() && doc["heating"]["minTemp"].is<unsigned char>()) { if (!doc["heating"]["minTemp"].isNull() && doc["heating"]["minTemp"].is<unsigned char>()) {
if (doc["heating"]["minTemp"].as<unsigned char>() >= 0 && doc["heating"]["minTemp"].as<unsigned char>() < 100 && doc["heating"]["minTemp"].as<unsigned char>() < settings.heating.maxTemp) { if (doc["heating"]["minTemp"].as<unsigned char>() >= 0 && doc["heating"]["minTemp"].as<unsigned char>() < 100 && doc["heating"]["minTemp"].as<unsigned char>() < settings.heating.maxTemp) {
settings.heating.minTemp = doc["heating"]["minTemp"].as<unsigned char>(); settings.heating.minTemp = doc["heating"]["minTemp"].as<unsigned char>();
vars.parameters.heatingMinTemp = settings.heating.minTemp;
flag = true; flag = true;
} }
} }
@@ -171,7 +169,6 @@ protected:
if (!doc["dhw"]["maxTemp"].isNull() && doc["dhw"]["maxTemp"].is<unsigned char>()) { if (!doc["dhw"]["maxTemp"].isNull() && doc["dhw"]["maxTemp"].is<unsigned char>()) {
if (doc["dhw"]["maxTemp"].as<unsigned char>() > 0 && doc["dhw"]["maxTemp"].as<unsigned char>() <= 100 && doc["dhw"]["maxTemp"].as<unsigned char>() > settings.dhw.minTemp) { if (doc["dhw"]["maxTemp"].as<unsigned char>() > 0 && doc["dhw"]["maxTemp"].as<unsigned char>() <= 100 && doc["dhw"]["maxTemp"].as<unsigned char>() > settings.dhw.minTemp) {
settings.dhw.maxTemp = doc["dhw"]["maxTemp"].as<unsigned char>(); settings.dhw.maxTemp = doc["dhw"]["maxTemp"].as<unsigned char>();
vars.parameters.dhwMaxTemp = settings.dhw.maxTemp;
flag = true; flag = true;
} }
} }
@@ -179,7 +176,6 @@ protected:
if (!doc["dhw"]["minTemp"].isNull() && doc["dhw"]["minTemp"].is<unsigned char>()) { if (!doc["dhw"]["minTemp"].isNull() && doc["dhw"]["minTemp"].is<unsigned char>()) {
if (doc["dhw"]["minTemp"].as<unsigned char>() >= 0 && doc["dhw"]["minTemp"].as<unsigned char>() < 100 && doc["dhw"]["minTemp"].as<unsigned char>() < settings.dhw.maxTemp) { if (doc["dhw"]["minTemp"].as<unsigned char>() >= 0 && doc["dhw"]["minTemp"].as<unsigned char>() < 100 && doc["dhw"]["minTemp"].as<unsigned char>() < settings.dhw.maxTemp) {
settings.dhw.minTemp = doc["dhw"]["minTemp"].as<unsigned char>(); settings.dhw.minTemp = doc["dhw"]["minTemp"].as<unsigned char>();
vars.parameters.dhwMinTemp = settings.dhw.minTemp;
flag = true; flag = true;
} }
} }
@@ -433,8 +429,8 @@ protected:
bool published = false; bool published = false;
bool isStupidMode = !settings.pid.enable && !settings.equitherm.enable; bool isStupidMode = !settings.pid.enable && !settings.equitherm.enable;
byte heatingMinTemp = isStupidMode ? vars.parameters.heatingMinTemp : 10; byte heatingMinTemp = isStupidMode ? settings.heating.minTemp : 10;
byte heatingMaxTemp = isStupidMode ? vars.parameters.heatingMaxTemp : 30; byte heatingMaxTemp = isStupidMode ? settings.heating.maxTemp : 30;
bool editableOutdoorTemp = settings.sensors.outdoor.type == 1; bool editableOutdoorTemp = settings.sensors.outdoor.type == 1;
bool editableIndoorTemp = settings.sensors.indoor.type == 1; bool editableIndoorTemp = settings.sensors.indoor.type == 1;
@@ -479,12 +475,12 @@ protected:
published = true; published = true;
} }
if (_dhwPresent && (force || _dhwMinTemp != vars.parameters.dhwMinTemp || _dhwMaxTemp != vars.parameters.dhwMaxTemp)) { if (_dhwPresent && (force || _dhwMinTemp != settings.dhw.minTemp || _dhwMaxTemp != settings.dhw.maxTemp)) {
_dhwMinTemp = vars.parameters.dhwMinTemp; _dhwMinTemp = settings.dhw.minTemp;
_dhwMaxTemp = vars.parameters.dhwMaxTemp; _dhwMaxTemp = settings.dhw.maxTemp;
haHelper.publishNumberDHWTarget(vars.parameters.dhwMinTemp, vars.parameters.dhwMaxTemp, false); haHelper.publishNumberDHWTarget(settings.dhw.minTemp, settings.dhw.maxTemp, false);
haHelper.publishClimateDHW(vars.parameters.dhwMinTemp, vars.parameters.dhwMaxTemp); haHelper.publishClimateDHW(settings.dhw.minTemp, settings.dhw.maxTemp);
published = true; published = true;
} }

View File

@@ -21,11 +21,6 @@ protected:
} }
void setup() { void setup() {
vars.parameters.heatingMinTemp = settings.heating.minTemp;
vars.parameters.heatingMaxTemp = settings.heating.maxTemp;
vars.parameters.dhwMinTemp = settings.dhw.minTemp;
vars.parameters.dhwMaxTemp = settings.dhw.maxTemp;
ot = new CustomOpenTherm(settings.opentherm.inPin, settings.opentherm.outPin); ot = new CustomOpenTherm(settings.opentherm.inPin, settings.opentherm.outPin);
ot->setHandleSendRequestCallback(this->sendRequestCallback); ot->setHandleSendRequestCallback(this->sendRequestCallback);
@@ -35,9 +30,9 @@ protected:
static_cast<OpenThermTask*>(self)->delay(10); static_cast<OpenThermTask*>(self)->delay(10);
}, this); }, this);
#ifdef LED_OT_RX_PIN #ifdef LED_OT_RX_PIN
pinMode(LED_OT_RX_PIN, OUTPUT); pinMode(LED_OT_RX_PIN, OUTPUT);
#endif #endif
} }
void loop() { void loop() {
@@ -53,10 +48,19 @@ protected:
} }
bool heatingEnabled = (vars.states.emergency || settings.heating.enable) && pump && isReady(); bool heatingEnabled = (vars.states.emergency || settings.heating.enable) && pump && isReady();
bool heatingCh2Enabled = settings.opentherm.heatingCh2Enabled;
if (settings.opentherm.heatingCh1ToCh2) {
heatingCh2Enabled = heatingEnabled;
}
localResponse = ot->setBoilerStatus( localResponse = ot->setBoilerStatus(
heatingEnabled, heatingEnabled,
settings.opentherm.dhwPresent && settings.dhw.enable, settings.opentherm.dhwPresent && settings.dhw.enable,
false, false, true, false, false false,
false,
heatingCh2Enabled,
settings.opentherm.summerWinterMode,
false
); );
if (!ot->isValidResponse(localResponse)) { if (!ot->isValidResponse(localResponse)) {
@@ -87,13 +91,34 @@ protected:
DEBUG_F("Slave type: %u, version: %u\r\n", vars.parameters.slaveType, vars.parameters.slaveVersion); DEBUG_F("Slave type: %u, version: %u\r\n", vars.parameters.slaveType, vars.parameters.slaveVersion);
if (settings.opentherm.dhwPresent) { if (settings.opentherm.dhwPresent) {
updateMinMaxDhwTemp(); if (updateMinMaxDhwTemp()) {
if (settings.dhw.minTemp < vars.parameters.dhwMinTemp || settings.dhw.maxTemp > vars.parameters.dhwMaxTemp) {
settings.dhw.minTemp = vars.parameters.dhwMinTemp;
settings.dhw.maxTemp = vars.parameters.dhwMaxTemp;
} }
updateMinMaxHeatingTemp();
} else {
WARN("Failed get min/max DHW temp");
}
}
if (updateMinMaxHeatingTemp()) {
if (settings.heating.minTemp < vars.parameters.heatingMinTemp || settings.heating.maxTemp > vars.parameters.heatingMaxTemp) {
settings.heating.minTemp = vars.parameters.heatingMinTemp;
settings.heating.maxTemp = vars.parameters.heatingMaxTemp;
} else {
WARN("Failed get min/max heating temp");
}
}
// force
setMaxHeatingTemp(settings.heating.maxTemp);
if (settings.sensors.outdoor.type == 0) { if (settings.sensors.outdoor.type == 0) {
updateOutsideTemp(); updateOutsideTemp();
} }
if (vars.states.fault) { if (vars.states.fault) {
updateFaultCode(); updateFaultCode();
ot->sendBoilerReset(); ot->sendBoilerReset();
@@ -129,8 +154,8 @@ protected:
// Температура ГВС // Температура ГВС
byte newDHWTemp = settings.dhw.target; byte newDHWTemp = settings.dhw.target;
if (settings.opentherm.dhwPresent && settings.dhw.enable && (needSetDhwTemp() || newDHWTemp != currentDHWTemp)) { if (settings.opentherm.dhwPresent && settings.dhw.enable && (needSetDhwTemp() || newDHWTemp != currentDHWTemp)) {
if (newDHWTemp < vars.parameters.dhwMinTemp || newDHWTemp > vars.parameters.dhwMaxTemp) { if (newDHWTemp < settings.dhw.minTemp || newDHWTemp > settings.dhw.maxTemp) {
newDHWTemp = constrain(newDHWTemp, vars.parameters.dhwMinTemp, vars.parameters.dhwMaxTemp); newDHWTemp = constrain(newDHWTemp, settings.dhw.minTemp, settings.dhw.maxTemp);
} }
INFO_F("Set DHW temp = %u\r\n", newDHWTemp); INFO_F("Set DHW temp = %u\r\n", newDHWTemp);
@@ -158,6 +183,12 @@ protected:
} else { } else {
WARN("Failed set heating temp"); WARN("Failed set heating temp");
} }
if (settings.opentherm.heatingCh1ToCh2) {
if (!ot->setBoilerTemperature2(vars.parameters.heatingSetpoint)) {
WARN("Failed set ch2 heating temp");
}
}
} }
// коммутационная разность (hysteresis) // коммутационная разность (hysteresis)
@@ -197,14 +228,14 @@ protected:
vars.states.otStatus = true; vars.states.otStatus = true;
} }
#ifdef LED_OT_RX_PIN #ifdef LED_OT_RX_PIN
{ {
digitalWrite(LED_OT_RX_PIN, true); digitalWrite(LED_OT_RX_PIN, true);
unsigned long ts = millis(); unsigned long ts = millis();
while (millis() - ts < 2) {} while (millis() - ts < 2) {}
digitalWrite(LED_OT_RX_PIN, false); digitalWrite(LED_OT_RX_PIN, false);
} }
#endif #endif
break; break;
default: default:
@@ -345,8 +376,8 @@ protected:
byte maxTemp = (response & 0xFFFF) >> 8; byte maxTemp = (response & 0xFFFF) >> 8;
if (minTemp >= 0 && maxTemp > 0 && maxTemp > minTemp) { if (minTemp >= 0 && maxTemp > 0 && maxTemp > minTemp) {
vars.parameters.dhwMinTemp = minTemp < settings.dhw.minTemp ? settings.dhw.minTemp : minTemp; vars.parameters.dhwMinTemp = minTemp;
vars.parameters.dhwMaxTemp = maxTemp > settings.dhw.maxTemp ? settings.dhw.maxTemp : maxTemp; vars.parameters.dhwMaxTemp = maxTemp;
return true; return true;
} }
@@ -364,15 +395,23 @@ protected:
byte maxTemp = (response & 0xFFFF) >> 8; byte maxTemp = (response & 0xFFFF) >> 8;
if (minTemp >= 0 && maxTemp > 0 && maxTemp > minTemp) { if (minTemp >= 0 && maxTemp > 0 && maxTemp > minTemp) {
vars.parameters.heatingMinTemp = minTemp < settings.heating.minTemp ? settings.heating.minTemp : minTemp; vars.parameters.heatingMinTemp = minTemp;
vars.parameters.heatingMaxTemp = maxTemp > settings.heating.maxTemp ? settings.heating.maxTemp : maxTemp; vars.parameters.heatingMaxTemp = maxTemp;
return true; return true;
} }
return false; return false;
} }
bool setMaxHeatingTemp(byte value) {
unsigned long response = ot->sendRequest(ot->buildRequest(OpenThermMessageType::WRITE_DATA, OpenThermMessageID::MaxTSet, ot->temperatureToData(value)));
if (!ot->isValidResponse(response)) {
return false;
}
return true;
}
bool updateOutsideTemp() { bool updateOutsideTemp() {
unsigned long response = ot->sendRequest(ot->buildRequest(OpenThermRequestType::READ, OpenThermMessageID::Toutside, 0)); unsigned long response = ot->sendRequest(ot->buildRequest(OpenThermRequestType::READ, OpenThermMessageID::Toutside, 0));
if (!ot->isValidResponse(response)) { if (!ot->isValidResponse(response)) {

View File

@@ -65,8 +65,8 @@ protected:
} }
// Ограничиваем, если до этого не ограничило // Ограничиваем, если до этого не ограничило
if (newTemp < vars.parameters.heatingMinTemp || newTemp > vars.parameters.heatingMaxTemp) { if (newTemp < settings.heating.minTemp || newTemp > settings.heating.maxTemp) {
newTemp = constrain(newTemp, vars.parameters.heatingMinTemp, vars.parameters.heatingMaxTemp); newTemp = constrain(newTemp, settings.heating.minTemp, settings.heating.maxTemp);
} }
if (abs(vars.parameters.heatingSetpoint - newTemp) + 0.0001 >= 1) { if (abs(vars.parameters.heatingSetpoint - newTemp) + 0.0001 >= 1) {
@@ -80,7 +80,7 @@ protected:
// if use equitherm // if use equitherm
if (settings.emergency.useEquitherm && settings.sensors.outdoor.type != 1) { if (settings.emergency.useEquitherm && settings.sensors.outdoor.type != 1) {
float etResult = getEquithermTemp(vars.parameters.heatingMinTemp, vars.parameters.heatingMaxTemp); 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) {
prevEtResult = etResult; prevEtResult = etResult;
@@ -115,7 +115,7 @@ protected:
// if use equitherm // if use equitherm
if (settings.equitherm.enable) { if (settings.equitherm.enable) {
float etResult = getEquithermTemp(vars.parameters.heatingMinTemp, vars.parameters.heatingMaxTemp); 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) {
prevEtResult = etResult; prevEtResult = etResult;
@@ -184,7 +184,7 @@ protected:
} else if (vars.tuning.regulator == 1) { } else if (vars.tuning.regulator == 1) {
// PID tuner // PID tuner
float defaultTemp = settings.equitherm.enable float defaultTemp = settings.equitherm.enable
? getEquithermTemp(vars.parameters.heatingMinTemp, vars.parameters.heatingMaxTemp) ? getEquithermTemp(settings.heating.minTemp, settings.heating.maxTemp)
: settings.heating.target; : settings.heating.target;
if (tunerInit && pidTuner.getState() == 3) { if (tunerInit && pidTuner.getState() == 3) {

View File

@@ -1,5 +1,5 @@
struct Settings { struct Settings {
bool debug = false; bool debug = DEBUG_BY_DEFAULT;
char hostname[80] = "opentherm"; char hostname[80] = "opentherm";
struct { struct {
@@ -7,6 +7,9 @@ struct Settings {
byte outPin = OT_OUT_PIN_DEFAULT; byte outPin = OT_OUT_PIN_DEFAULT;
unsigned int memberIdCode = 0; unsigned int memberIdCode = 0;
bool dhwPresent = true; bool dhwPresent = true;
bool summerWinterMode = false;
bool heatingCh2Enabled = true;
bool heatingCh1ToCh2 = false;
} opentherm; } opentherm;
struct { struct {

View File

@@ -16,6 +16,9 @@ UnsignedIntParameter* wmOtInPin;
UnsignedIntParameter* wmOtOutPin; UnsignedIntParameter* wmOtOutPin;
UnsignedIntParameter* wmOtMemberIdCode; UnsignedIntParameter* wmOtMemberIdCode;
CheckboxParameter* wmOtDHWPresent; CheckboxParameter* wmOtDHWPresent;
CheckboxParameter* wmOtSummerWinterMode;
CheckboxParameter* wmOtHeatingCh2Enabled;
CheckboxParameter* wmOtHeatingCh1ToCh2;
UnsignedIntParameter* wmOutdoorSensorPin; UnsignedIntParameter* wmOutdoorSensorPin;
UnsignedIntParameter* wmIndoorSensorPin; UnsignedIntParameter* wmIndoorSensorPin;
@@ -40,8 +43,11 @@ protected:
} }
void setup() { void setup() {
wm.setDebugOutput(settings.debug); #ifdef WOKWI
//wm.setDebugOutput(settings.debug, WM_DEBUG_VERBOSE); WiFi.begin("Wokwi-GUEST", "", 6);
#endif
wm.setDebugOutput(settings.debug, WM_DEBUG_MODE);
wm.setTitle("OpenTherm Gateway"); wm.setTitle("OpenTherm Gateway");
wm.setCustomMenuHTML(PSTR( wm.setCustomMenuHTML(PSTR(
@@ -91,6 +97,15 @@ protected:
wmOtDHWPresent = new CheckboxParameter("ot_dhw_present", "Opentherm DHW present", settings.opentherm.dhwPresent); wmOtDHWPresent = new CheckboxParameter("ot_dhw_present", "Opentherm DHW present", settings.opentherm.dhwPresent);
wm.addParameter(wmOtDHWPresent); wm.addParameter(wmOtDHWPresent);
wmOtSummerWinterMode = new CheckboxParameter("ot_summer_winter_mode", "Opentherm summer/winter mode", settings.opentherm.summerWinterMode);
wm.addParameter(wmOtSummerWinterMode);
wmOtHeatingCh2Enabled = new CheckboxParameter("ot_heating_ch2_enabled", "Opentherm CH2 enabled", settings.opentherm.heatingCh2Enabled);
wm.addParameter(wmOtHeatingCh2Enabled);
wmOtHeatingCh1ToCh2 = new CheckboxParameter("ot_heating_ch1_to_ch2", "Opentherm heating CH1 to CH2", settings.opentherm.heatingCh1ToCh2);
wm.addParameter(wmOtHeatingCh1ToCh2);
wmSep2 = new SeparatorParameter(); wmSep2 = new SeparatorParameter();
wm.addParameter(wmSep2); wm.addParameter(wmSep2);
@@ -122,7 +137,13 @@ protected:
wm.stopWebPortal(); wm.stopWebPortal();
} }
#ifdef USE_TELNET wm.setCaptivePortalEnable(true);
if (!wm.getConfigPortalActive()) {
wm.startConfigPortal();
}
#if USE_TELNET
TelnetStream.stop(); TelnetStream.stop();
#endif #endif
@@ -136,11 +157,13 @@ protected:
wm.stopConfigPortal(); wm.stopConfigPortal();
} }
wm.setCaptivePortalEnable(false);
if (!wm.getWebPortalActive()) { if (!wm.getWebPortalActive()) {
wm.startWebPortal(); wm.startWebPortal();
} }
#ifdef USE_TELNET #if USE_TELNET
TelnetStream.begin(); TelnetStream.begin();
#endif #endif
@@ -230,6 +253,24 @@ protected:
settings.opentherm.dhwPresent = wmOtDHWPresent->getCheckboxValue(); settings.opentherm.dhwPresent = wmOtDHWPresent->getCheckboxValue();
} }
if (wmOtSummerWinterMode->getCheckboxValue() != settings.opentherm.summerWinterMode) {
changed = true;
settings.opentherm.summerWinterMode = wmOtSummerWinterMode->getCheckboxValue();
}
if (wmOtHeatingCh2Enabled->getCheckboxValue() != settings.opentherm.heatingCh2Enabled) {
changed = true;
settings.opentherm.heatingCh2Enabled = wmOtHeatingCh2Enabled->getCheckboxValue();
}
if (wmOtHeatingCh1ToCh2->getCheckboxValue() != settings.opentherm.heatingCh1ToCh2) {
changed = true;
settings.opentherm.heatingCh1ToCh2 = wmOtHeatingCh1ToCh2->getCheckboxValue();
}
if (wmOutdoorSensorPin->getValue() != settings.sensors.outdoor.pin) { if (wmOutdoorSensorPin->getValue() != settings.sensors.outdoor.pin) {
changed = true; changed = true;
needRestart = true; needRestart = true;
@@ -265,6 +306,9 @@ protected:
" OT out pin: %d\r\n" " OT out pin: %d\r\n"
" OT member id code: %d\r\n" " OT member id code: %d\r\n"
" OT DHW present: %d\r\n" " OT DHW present: %d\r\n"
" OT summer/winter mode: %d\r\n"
" OT heating ch2 enabled: %d\r\n"
" OT heating ch1 to ch2: %d\r\n"
" Outdoor sensor pin: %d\r\n" " Outdoor sensor pin: %d\r\n"
" Indoor sensor pin: %d\r\n", " Indoor sensor pin: %d\r\n",
settings.hostname, settings.hostname,
@@ -278,6 +322,9 @@ protected:
settings.opentherm.outPin, settings.opentherm.outPin,
settings.opentherm.memberIdCode, settings.opentherm.memberIdCode,
settings.opentherm.dhwPresent, settings.opentherm.dhwPresent,
settings.opentherm.summerWinterMode,
settings.opentherm.heatingCh2Enabled,
settings.opentherm.heatingCh1ToCh2,
settings.sensors.outdoor.pin, settings.sensors.outdoor.pin,
settings.sensors.indoor.pin settings.sensors.indoor.pin
); );

View File

@@ -0,0 +1,12 @@
{
"version": 1,
"editor": "wokwi",
"parts": [
{ "type": "wokwi-esp32-devkit-v1", "id": "esp", "top": 0, "left": 0, "attrs": {} }
],
"connections": [
[ "esp:TX0", "$serialMonitor:RX", "", [] ],
[ "esp:RX0", "$serialMonitor:TX", "", [] ]
]
}

View File

@@ -0,0 +1,8 @@
[wokwi]
version = 1
elf = "../../.pio/build/nodemcu_32s/firmware.elf"
firmware = "../../.pio/build/nodemcu_32s/firmware.bin"
[[net.forward]]
from = "localhost:9080"
to = "target:80"