mirror of
https://github.com/Laxilef/OTGateway.git
synced 2025-12-10 18:24:27 +05:00
features
* 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:
@@ -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
|
||||||
|
|||||||
@@ -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}
|
||||||
@@ -154,4 +160,9 @@ build_flags =
|
|||||||
-D SENSOR_OUTDOOR_PIN_DEFAULT=12
|
-D SENSOR_OUTDOOR_PIN_DEFAULT=12
|
||||||
-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
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
WARN("Failed get min/max DHW temp");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updateMinMaxHeatingTemp();
|
|
||||||
|
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)) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,8 +137,14 @@ protected:
|
|||||||
wm.stopWebPortal();
|
wm.stopWebPortal();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_TELNET
|
wm.setCaptivePortalEnable(true);
|
||||||
TelnetStream.stop();
|
|
||||||
|
if (!wm.getConfigPortalActive()) {
|
||||||
|
wm.startConfigPortal();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_TELNET
|
||||||
|
TelnetStream.stop();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
INFO("[wifi] Disconnected");
|
INFO("[wifi] Disconnected");
|
||||||
@@ -136,12 +157,14 @@ 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
|
||||||
|
|
||||||
INFO_F("[wifi] Connected. IP address: %s, RSSI: %d\n", WiFi.localIP().toString().c_str(), WiFi.RSSI());
|
INFO_F("[wifi] Connected. IP address: %s, RSSI: %d\n", WiFi.localIP().toString().c_str(), WiFi.RSSI());
|
||||||
@@ -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
|
||||||
);
|
);
|
||||||
|
|||||||
12
wokwi/nodemcu_32s/diagram.json
Normal file
12
wokwi/nodemcu_32s/diagram.json
Normal 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", "", [] ]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
8
wokwi/nodemcu_32s/wokwi.toml
Normal file
8
wokwi/nodemcu_32s/wokwi.toml
Normal 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"
|
||||||
Reference in New Issue
Block a user