feat: setting the cooling setpoint if cooling support is enabled

This commit is contained in:
Yurii
2025-10-09 22:57:04 +03:00
parent cc5bbb7a87
commit 78b5a12e90
10 changed files with 70 additions and 12 deletions

View File

@@ -236,7 +236,7 @@ protected:
vars.slave.heating.active = CustomOpenTherm::isCentralHeatingActive(response); vars.slave.heating.active = CustomOpenTherm::isCentralHeatingActive(response);
vars.slave.dhw.active = settings.opentherm.options.dhwSupport ? CustomOpenTherm::isHotWaterActive(response) : false; vars.slave.dhw.active = settings.opentherm.options.dhwSupport ? CustomOpenTherm::isHotWaterActive(response) : false;
vars.slave.flame = CustomOpenTherm::isFlameOn(response); vars.slave.flame = CustomOpenTherm::isFlameOn(response);
vars.slave.cooling = CustomOpenTherm::isCoolingActive(response); vars.slave.cooling.active = CustomOpenTherm::isCoolingActive(response);
vars.slave.ch2.active = CustomOpenTherm::isCh2Active(response); vars.slave.ch2.active = CustomOpenTherm::isCh2Active(response);
vars.slave.fault.active = CustomOpenTherm::isFault(response); vars.slave.fault.active = CustomOpenTherm::isFault(response);
@@ -250,7 +250,7 @@ protected:
Log.snoticeln( Log.snoticeln(
FPSTR(L_OT), F("Received boiler status. Heating: %hhu; DHW: %hhu; flame: %hhu; cooling: %hhu; channel 2: %hhu; fault: %hhu; diag: %hhu"), FPSTR(L_OT), F("Received boiler status. Heating: %hhu; DHW: %hhu; flame: %hhu; cooling: %hhu; channel 2: %hhu; fault: %hhu; diag: %hhu"),
vars.slave.heating.active, vars.slave.dhw.active, vars.slave.heating.active, vars.slave.dhw.active,
vars.slave.flame, vars.slave.cooling, vars.slave.ch2.active, vars.slave.fault.active, vars.slave.diag.active vars.slave.flame, vars.slave.cooling.active, vars.slave.ch2.active, vars.slave.fault.active, vars.slave.diag.active
); );
} }
@@ -318,6 +318,8 @@ protected:
vars.slave.dhw.enabled = false; vars.slave.dhw.enabled = false;
vars.slave.dhw.active = false; vars.slave.dhw.active = false;
vars.slave.flame = false; vars.slave.flame = false;
vars.slave.cooling.active = false;
vars.slave.cooling.setpoint = 0;
vars.slave.fault.active = false; vars.slave.fault.active = false;
vars.slave.fault.code = 0; vars.slave.fault.code = 0;
vars.slave.diag.active = false; vars.slave.diag.active = false;
@@ -688,6 +690,22 @@ protected:
this->prevUpdateNonEssentialVars = millis(); this->prevUpdateNonEssentialVars = millis();
} }
// Set cooling setpoint = heating max modulation
if (settings.opentherm.options.coolingSupport) {
if (this->setCoolingSetpoint(settings.heating.maxModulation)) {
Log.snoticeln(
FPSTR(L_OT), F("Set cooling setpoint: %hhu%% (response: %hhu%%)"),
settings.heating.maxModulation, vars.slave.cooling.setpoint
);
} else {
Log.swarningln(
FPSTR(L_OT), F("Failed set cooling setpoint: %hhu%% (response: %hhu%%)"),
settings.heating.maxModulation, vars.slave.cooling.setpoint
);
}
}
// Set max modulation level // Set max modulation level
uint8_t targetMaxModulation = vars.slave.modulation.max; uint8_t targetMaxModulation = vars.slave.modulation.max;
if (vars.slave.heating.active) { if (vars.slave.heating.active) {
@@ -1568,6 +1586,26 @@ protected:
return CustomOpenTherm::getUInt(response) == request; return CustomOpenTherm::getUInt(response) == request;
} }
bool setCoolingSetpoint(const uint8_t value) {
const unsigned int request = CustomOpenTherm::toFloat(value);
const unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(
OpenThermRequestType::WRITE_DATA,
OpenThermMessageID::CoolingControl,
request
));
if (!CustomOpenTherm::isValidResponse(response)) {
return false;
} else if (!CustomOpenTherm::isValidResponseId(response, OpenThermMessageID::CoolingControl)) {
return false;
}
vars.slave.cooling.setpoint = CustomOpenTherm::getFloat(response);
return CustomOpenTherm::getUInt(response) == request;
}
bool setMaxModulationLevel(const uint8_t value) { bool setMaxModulationLevel(const uint8_t value) {
const unsigned int request = CustomOpenTherm::toFloat(value); const unsigned int request = CustomOpenTherm::toFloat(value);
const unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest( const unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest(

View File

@@ -329,10 +329,14 @@ struct Variables {
bool connected = false; bool connected = false;
bool flame = false; bool flame = false;
bool cooling = false;
float pressure = 0.0f; float pressure = 0.0f;
float heatExchangerTemp = 0.0f; float heatExchangerTemp = 0.0f;
struct {
bool active = false;
uint8_t setpoint = 0;
} cooling;
struct { struct {
bool active = false; bool active = false;
uint8_t code = 0; uint8_t code = 0;

View File

@@ -190,6 +190,7 @@ const char S_STA[] PROGMEM = "sta";
const char S_STATE[] PROGMEM = "state"; const char S_STATE[] PROGMEM = "state";
const char S_STATIC_CONFIG[] PROGMEM = "staticConfig"; const char S_STATIC_CONFIG[] PROGMEM = "staticConfig";
const char S_STATUS_LED_GPIO[] PROGMEM = "statusLedGpio"; const char S_STATUS_LED_GPIO[] PROGMEM = "statusLedGpio";
const char S_SETPOINT[] PROGMEM = "setpoint";
const char S_SETPOINT_TEMP[] PROGMEM = "setpointTemp"; const char S_SETPOINT_TEMP[] PROGMEM = "setpointTemp";
const char S_SUBNET[] PROGMEM = "subnet"; const char S_SUBNET[] PROGMEM = "subnet";
const char S_SUMMER_WINTER_MODE[] PROGMEM = "summerWinterMode"; const char S_SUMMER_WINTER_MODE[] PROGMEM = "summerWinterMode";

View File

@@ -2060,7 +2060,10 @@ void varsToJson(const Variables& src, JsonVariant dst) {
slave[FPSTR(S_PROTOCOL_VERSION)] = src.slave.appVersion; slave[FPSTR(S_PROTOCOL_VERSION)] = src.slave.appVersion;
slave[FPSTR(S_CONNECTED)] = src.slave.connected; slave[FPSTR(S_CONNECTED)] = src.slave.connected;
slave[FPSTR(S_FLAME)] = src.slave.flame; slave[FPSTR(S_FLAME)] = src.slave.flame;
slave[FPSTR(S_COOLING)] = src.slave.cooling;
auto sCooling = slave[FPSTR(S_COOLING)].to<JsonObject>();
sCooling[FPSTR(S_ACTIVE)] = src.slave.cooling.active;
sCooling[FPSTR(S_SETPOINT)] = src.slave.cooling.setpoint;
auto sModulation = slave[FPSTR(S_MODULATION)].to<JsonObject>(); auto sModulation = slave[FPSTR(S_MODULATION)].to<JsonObject>();
sModulation[FPSTR(S_MIN)] = src.slave.modulation.min; sModulation[FPSTR(S_MIN)] = src.slave.modulation.min;

View File

@@ -109,7 +109,8 @@
"sConnected": "OpenTherm 通讯状态", "sConnected": "OpenTherm 通讯状态",
"sFlame": "火焰", "sFlame": "火焰",
"sCooling": "制冷", "sCoolingActive": "制冷",
"sCoolingSetpoint": "冷却设定点",
"sFaultActive": "报警状态", "sFaultActive": "报警状态",
"sFaultCode": "报警代码", "sFaultCode": "报警代码",
"sDiagActive": "诊断状态", "sDiagActive": "诊断状态",

View File

@@ -109,7 +109,8 @@
"sConnected": "OpenTherm connection", "sConnected": "OpenTherm connection",
"sFlame": "Flame", "sFlame": "Flame",
"sCooling": "Cooling", "sCoolingActive": "Cooling",
"sCoolingSetpoint": "Cooling setpoint",
"sFaultActive": "Fault", "sFaultActive": "Fault",
"sFaultCode": "Fault code", "sFaultCode": "Fault code",
"sDiagActive": "Diagnostic", "sDiagActive": "Diagnostic",

View File

@@ -109,7 +109,8 @@
"sConnected": "Connessione OpenTherm", "sConnected": "Connessione OpenTherm",
"sFlame": "Fiamma", "sFlame": "Fiamma",
"sCooling": "Raffrescamento", "sCoolingActive": "Raffrescamento",
"sCoolingSetpoint": "Raffrescamento setpoint",
"sFaultActive": "Anomalia", "sFaultActive": "Anomalia",
"sFaultCode": "Codice anomalia", "sFaultCode": "Codice anomalia",
"sDiagActive": "Diagnostica", "sDiagActive": "Diagnostica",

View File

@@ -99,7 +99,8 @@
"mCascadeControlOutput": "Cascaderegeling (uitgang)", "mCascadeControlOutput": "Cascaderegeling (uitgang)",
"sConnected": "OpenTherm-verbinding", "sConnected": "OpenTherm-verbinding",
"sFlame": "Vlam", "sFlame": "Vlam",
"sCooling": "Koeling", "sCoolingActive": "Koeling",
"sCoolingSetpoint": "Koelinstelpunt",
"sFaultActive": "Storing", "sFaultActive": "Storing",
"sFaultCode": "Storingscode", "sFaultCode": "Storingscode",
"sDiagActive": "Diagnose", "sDiagActive": "Diagnose",

View File

@@ -109,7 +109,8 @@
"sConnected": "Подключение к OpenTherm", "sConnected": "Подключение к OpenTherm",
"sFlame": "Пламя", "sFlame": "Пламя",
"sCooling": "Охлаждение", "sCoolingActive": "Охлаждение",
"sCoolingSetpoint": "Охлаждение, уставка",
"sFaultActive": "Ошибка", "sFaultActive": "Ошибка",
"sFaultCode": "Код ошибки", "sFaultCode": "Код ошибки",
"sDiagActive": "Диагностика", "sDiagActive": "Диагностика",

View File

@@ -154,9 +154,14 @@
<th scope="row" data-i18n>dashboard.states.sFlame</th> <th scope="row" data-i18n>dashboard.states.sFlame</th>
<td><i class="sFlame"></i></td> <td><i class="sFlame"></i></td>
</tr> </tr>
<tr> <tr>
<th scope="row" data-i18n>dashboard.states.sCooling</th> <th scope="row" data-i18n>dashboard.states.sCoolingActive</th>
<td><i class="sCooling"></i></td> <td><i class="sCoolingActive"></i></td>
</tr>
<tr>
<th scope="row" data-i18n>dashboard.states.sCoolingSetpoint</th>
<td><b class="sCoolingSetpoint"></b> %</td>
</tr> </tr>
@@ -558,7 +563,9 @@
result.slave.connected ? "green" : "red" result.slave.connected ? "green" : "red"
); );
setState('.sFlame', result.slave.flame); setState('.sFlame', result.slave.flame);
setState('.sCooling', result.slave.cooling);
setState('.sCoolingActive', result.slave.cooling.active);
setValue('.sCoolingSetpoint', result.slave.cooling.setpoint);
setValue('.sModMin', result.slave.modulation.min); setValue('.sModMin', result.slave.modulation.min);
setValue('.sModMax', result.slave.modulation.max); setValue('.sModMax', result.slave.modulation.max);