Heap fragmentation optimization

Moving object creation to task constructors
This commit is contained in:
Yurii
2023-12-16 05:05:37 +03:00
parent 214e840ec2
commit 7149f52d62
10 changed files with 244 additions and 137 deletions

View File

@@ -71,6 +71,9 @@ public:
}
bool result = this->writer->publish(topic, doc, true);
doc.clear();
doc.shrinkToFit();
if (this->eventPublishCallback) {
this->eventPublishCallback(topic, result);
}

View File

@@ -96,7 +96,6 @@ public:
size_t written = 0;
if (this->client->beginPublish(topic, docSize, retained)) {
serializeJson(doc, *this);
doc.clear();
this->flush();
written = this->writeAfterLock;

View File

@@ -32,7 +32,7 @@ build_flags =
-D USE_TELNET=1
upload_speed = 921600
monitor_speed = 115200
version = 1.4.0-rc.1
version = 1.4.0-rc.2
; Defaults
[esp8266_defaults]

View File

@@ -21,6 +21,7 @@ public:
doc[FPSTR(HA_OPTIONS)][1] = F("Manual");
doc[FPSTR(HA_OPTIONS)][2] = F("External");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("select", "outdoor_sensor_type").c_str(), doc);
}
@@ -50,6 +51,7 @@ public:
doc[FPSTR(HA_OPTIONS)][2] = F("Bluetooth");
#endif
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("select", "indoor_sensor_type").c_str(), doc);
}
@@ -75,6 +77,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "outdoor_sensor_offset").c_str(), doc);
}
@@ -100,6 +103,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "indoor_sensor_offset").c_str(), doc);
}
@@ -121,6 +125,7 @@ public:
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"debug\": true}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"debug\": false}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("switch", "debug").c_str(), doc);
}
@@ -142,6 +147,7 @@ public:
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"emergency\": {\"enable\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"emergency\": {\"enable\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("switch", "emergency").c_str(), doc);
}
@@ -165,6 +171,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.5;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "emergency_target").c_str(), doc);
}
@@ -187,6 +194,7 @@ public:
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"emergency\": {\"useEquitherm\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"emergency\": {\"useEquitherm\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("switch", "emergency_use_equitherm").c_str(), doc);
}
@@ -209,6 +217,7 @@ public:
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"heating\": {\"enable\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"heating\": {\"enable\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("switch", "heating").c_str(), doc);
}
@@ -230,6 +239,7 @@ public:
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"heating\": {\"turbo\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"heating\": {\"turbo\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("switch", "heating_turbo").c_str(), doc);
}
@@ -254,6 +264,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.5;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "heating_target").c_str(), doc);
}
@@ -277,6 +288,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "heating_hysteresis").c_str(), doc);
}
@@ -296,6 +308,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.parameters.heatingSetpoint|int(0) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "heating_setpoint").c_str(), doc);
}
@@ -315,6 +328,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.parameters.heatingMinTemp|int(0) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "current_heating_min_temp").c_str(), doc);
}
@@ -334,6 +348,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.parameters.heatingMaxTemp|int(0) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "current_heating_max_temp").c_str(), doc);
}
@@ -357,6 +372,7 @@ public:
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "heating_min_temp").c_str(), doc);
}
@@ -380,6 +396,7 @@ public:
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "heating_max_temp").c_str(), doc);
}
@@ -403,6 +420,7 @@ public:
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "heating_max_modulation").c_str(), doc);
}
@@ -425,6 +443,7 @@ public:
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"dhw\": {\"enable\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"dhw\": {\"enable\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("switch", "dhw").c_str(), doc);
}
@@ -449,6 +468,7 @@ public:
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "dhw_target").c_str(), doc);
}
@@ -468,6 +488,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.parameters.dhwMinTemp|int(0) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "current_dhw_min_temp").c_str(), doc);
}
@@ -487,6 +508,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.parameters.dhwMaxTemp|int(0) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "current_dhw_max_temp").c_str(), doc);
}
@@ -510,6 +532,7 @@ public:
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "dhw_min_temp").c_str(), doc);
}
@@ -533,6 +556,7 @@ public:
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "dhw_max_temp").c_str(), doc);
}
@@ -554,6 +578,7 @@ public:
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"pid\": {\"enable\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"pid\": {\"enable\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("switch", "pid").c_str(), doc);
}
@@ -574,6 +599,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.001;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "pid_p_factor").c_str(), doc);
}
@@ -594,6 +620,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.001;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "pid_i_factor").c_str(), doc);
}
@@ -614,6 +641,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.001;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "pid_d_factor").c_str(), doc);
}
@@ -637,6 +665,7 @@ public:
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "pid_min_temp").c_str(), doc);
}
@@ -660,6 +689,7 @@ public:
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "pid_max_temp").c_str(), doc);
}
@@ -681,6 +711,7 @@ public:
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"equitherm\": {\"enable\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"equitherm\": {\"enable\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("switch", "equitherm").c_str(), doc);
}
@@ -701,6 +732,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.001;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "equitherm_n_factor").c_str(), doc);
}
@@ -721,6 +753,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.01;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "equitherm_k_factor").c_str(), doc);
}
@@ -743,6 +776,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.01;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "equitherm_t_factor").c_str(), doc);
}
@@ -764,6 +798,7 @@ public:
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"tuning\": {\"enable\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"tuning\": {\"enable\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("switch", "tuning").c_str(), doc);
}
@@ -784,6 +819,7 @@ public:
doc[FPSTR(HA_OPTIONS)][0] = F("Equitherm");
doc[FPSTR(HA_OPTIONS)][1] = F("PID");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("select", "tuning_regulator").c_str(), doc);
}
@@ -801,6 +837,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("status");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value == 'online', 'OFF', 'ON') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 60;
doc.shrinkToFit();
return this->publish(this->getTopic("binary_sensor", "status").c_str(), doc);
}
@@ -817,6 +854,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.states.otStatus, 'OFF', 'ON') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("binary_sensor", "ot_status").c_str(), doc);
}
@@ -834,6 +872,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.states.heating, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("binary_sensor", "heating").c_str(), doc);
}
@@ -851,6 +890,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.states.dhw, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("binary_sensor", "dhw").c_str(), doc);
}
@@ -868,6 +908,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.states.flame, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("binary_sensor", "flame").c_str(), doc);
}
@@ -886,6 +927,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.states.fault, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("binary_sensor", "fault").c_str(), doc);
}
@@ -903,6 +945,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.states.diagnostic, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("binary_sensor", "diagnostic").c_str(), doc);
}
@@ -920,6 +963,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ \"E%02d\"|format(value_json.sensors.faultCode) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "fault_code").c_str(), doc);
}
@@ -939,6 +983,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.sensors.rssi|float(0)|round(1) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "rssi").c_str(), doc);
}
@@ -958,6 +1003,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.sensors.uptime|int(0) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "uptime").c_str(), doc);
}
@@ -978,6 +1024,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.sensors.modulation|float(0)|round(0) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "modulation").c_str(), doc);
}
@@ -997,6 +1044,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.sensors.pressure|float(0)|round(2) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "pressure").c_str(), doc);
}
@@ -1016,6 +1064,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.sensors.dhwFlowRate|float(0)|round(2) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "dhw_flow_rate").c_str(), doc);
}
@@ -1039,6 +1088,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.01;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "indoor_temp").c_str(), doc);
}
@@ -1059,6 +1109,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.temperatures.indoor|float(0)|round(1) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "indoor_temp").c_str(), doc);
}
@@ -1081,6 +1132,7 @@ public:
doc[FPSTR(HA_STEP)] = 0.01;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("number", "outdoor_temp").c_str(), doc);
}
@@ -1101,6 +1153,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.temperatures.outdoor|float(0)|round(1) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "outdoor_temp").c_str(), doc);
}
@@ -1120,6 +1173,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.temperatures.heating|float(0)|round(2) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "heating_temp").c_str(), doc);
}
@@ -1139,6 +1193,7 @@ public:
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic("state");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.temperatures.dhw|float(0)|round(2) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("sensor", "dhw_temp").c_str(), doc);
}
@@ -1192,6 +1247,7 @@ public:
doc[FPSTR(HA_MAX_TEMP)] = maxTemp;
doc[FPSTR(HA_TEMP_STEP)] = 0.5;
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("climate", "heating", '_').c_str(), doc);
}
@@ -1228,6 +1284,7 @@ public:
doc[FPSTR(HA_MIN_TEMP)] = minTemp;
doc[FPSTR(HA_MAX_TEMP)] = maxTemp;
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("climate", "dhw", '_').c_str(), doc);
}
@@ -1244,6 +1301,7 @@ public:
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic("state/set");
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"actions\": {\"restart\": true}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("button", "restart").c_str(), doc);
}
@@ -1261,6 +1319,7 @@ public:
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic("state/set");
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"actions\": {\"resetFault\": true}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("button", "reset_fault").c_str(), doc);
}
@@ -1278,6 +1337,7 @@ public:
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic("state/set");
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"actions\": {\"resetDiagnostic\": true}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 120;
doc.shrinkToFit();
return this->publish(this->getTopic("button", "reset_diagnostic").c_str(), doc);
}

View File

@@ -11,13 +11,22 @@ extern EEManager eeSettings;
class MainTask : public Task {
public:
MainTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {}
MainTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {
this->blinker = new Blinker();
}
~MainTask() {
if (this->blinker != nullptr) {
delete this->blinker;
}
}
protected:
const static byte REASON_PUMP_START_HEATING = 1;
const static byte REASON_PUMP_START_ANTISTUCK = 2;
Blinker* blinker = nullptr;
bool blinkerInitialized = false;
unsigned long lastHeapInfo = 0;
unsigned long firstFailConnect = 0;
unsigned int heapSize = 0;
@@ -192,8 +201,9 @@ protected:
static unsigned long endBlinkTime = 0;
static bool ledOn = false;
if (this->blinker == nullptr) {
this->blinker = new Blinker(ledPin);
if (!this->blinkerInitialized) {
this->blinker->init(ledPin);
this->blinkerInitialized = true;
}
if (WiFi.status() != WL_CONNECTED) {

View File

@@ -7,7 +7,12 @@
class MqttTask : public Task {
public:
MqttTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {}
MqttTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {
this->wifiClient = new MqttWiFiClient();
this->client = new PubSubClient();
this->writer = new MqttWriter(this->client, 256);
this->haHelper = new HaHelper();
}
~MqttTask() {
if (this->haHelper != nullptr) {
@@ -64,11 +69,10 @@ protected:
void setup() {
Log.sinfoln("MQTT", F("Started"));
this->wifiClient = new MqttWiFiClient();
// wificlient settings
this->wifiClient->setSync(true);
// client settings
this->client = new PubSubClient();
this->client->setClient(*this->wifiClient);
this->client->setSocketTimeout(3);
this->client->setKeepAlive(15);
@@ -77,8 +81,7 @@ protected:
this->onMessage(topic, payload, length);
});
// writer
this->writer = new MqttWriter(this->client, 256);
// writer settings
this->writer->setYieldCallback([this] {
this->delay(10);
});
@@ -86,7 +89,7 @@ protected:
Log.straceln("MQTT", F("%s publish %u of %u bytes to topic: %s"), result ? F("Successfully") : F("Failed"), written, length, topic);
this->client->loop();
this->delay(100);
this->delay(250);
});
this->writer->setEventFlushCallback([this] (size_t, size_t) {
if (!this->wifiClient->getSync() && this->wifiClient->connected()) {
@@ -99,7 +102,6 @@ protected:
});
// ha helper settings
this->haHelper = new HaHelper();
this->haHelper->setDevicePrefix(settings.mqtt.prefix);
this->haHelper->setDeviceVersion(PROJECT_VERSION);
this->haHelper->setDeviceModel(PROJECT_NAME);
@@ -445,6 +447,9 @@ protected:
}
}
doc.clear();
doc.shrinkToFit();
if (flag) {
this->prevPubSettingsTime = 0;
eeSettings.update();
@@ -499,6 +504,9 @@ protected:
vars.actions.resetDiagnostic = true;
}
doc.clear();
doc.shrinkToFit();
if (flag) {
this->prevPubVarsTime = 0;
return true;
@@ -723,6 +731,8 @@ protected:
doc["sensors"]["indoor"]["type"] = settings.sensors.indoor.type;
doc["sensors"]["indoor"]["offset"] = settings.sensors.indoor.offset;
doc.shrinkToFit();
return this->writer->publish(topic, doc, true);
}
@@ -758,6 +768,8 @@ protected:
doc["parameters"]["dhwMinTemp"] = vars.parameters.dhwMinTemp;
doc["parameters"]["dhwMaxTemp"] = vars.parameters.dhwMaxTemp;
doc.shrinkToFit();
return this->writer->publish(topic, doc, true);
}
};

View File

@@ -11,7 +11,9 @@ const char S_OT_HEATING[] PROGMEM = "OT.HEATING";
class OpenThermTask : public Task {
public:
OpenThermTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {}
OpenThermTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {
ot = new CustomOpenTherm(settings.opentherm.inPin, settings.opentherm.outPin);
}
static void IRAM_ATTR handleInterrupt() {
ot->handleInterrupt();
@@ -44,8 +46,6 @@ protected:
void setup() {
Log.sinfoln(FPSTR(S_OT), F("Started. GPIO IN: %hhu, GPIO OUT: %hhu"), settings.opentherm.inPin, settings.opentherm.outPin);
ot = new CustomOpenTherm(settings.opentherm.inPin, settings.opentherm.outPin);
ot->setHandleSendRequestCallback(OpenThermTask::sendRequestCallback);
ot->setYieldCallback([](void* self) {
static_cast<OpenThermTask*>(self)->delay(25);
@@ -95,7 +95,7 @@ protected:
static byte currentHeatingTemp, currentDhwTemp = 0;
unsigned long localResponse;
bool heatingEnabled = (vars.states.emergency || settings.heating.enable) && pump && isReady();
bool heatingEnabled = (vars.states.emergency || settings.heating.enable) && this->pump && isReady();
bool heatingCh2Enabled = settings.opentherm.heatingCh2Enabled;
if (settings.opentherm.heatingCh1ToCh2) {
heatingCh2Enabled = heatingEnabled;
@@ -135,7 +135,7 @@ protected:
}
if (vars.parameters.heatingEnabled != heatingEnabled) {
prevUpdateNonEssentialVars = 0;
this->prevUpdateNonEssentialVars = 0;
vars.parameters.heatingEnabled = heatingEnabled;
Log.sinfoln(FPSTR(S_OT_HEATING), "%s", heatingEnabled ? F("Enabled") : F("Disabled"));
}
@@ -147,7 +147,7 @@ protected:
vars.states.diagnostic = ot->isDiagnostic(localResponse);
// These parameters will be updated every minute
if (millis() - prevUpdateNonEssentialVars > 60000) {
if (millis() - this->prevUpdateNonEssentialVars > 60000) {
if (!heatingEnabled && settings.opentherm.modulationSyncWithHeating) {
if (setMaxModulationLevel(0)) {
Log.snoticeln(FPSTR(S_OT_HEATING), F("Set max modulation 0% (off)"));
@@ -233,7 +233,7 @@ protected:
updatePressure();
prevUpdateNonEssentialVars = millis();
this->prevUpdateNonEssentialVars = millis();
//yield();
}
@@ -301,7 +301,7 @@ protected:
// Записываем заданную температуру ГВС
if (ot->setDhwTemp(newDhwTemp)) {
currentDhwTemp = newDhwTemp;
dhwSetTempTime = millis();
this->dhwSetTempTime = millis();
} else {
Log.swarningln(FPSTR(S_OT_DHW), F("Failed set temp"));
@@ -324,7 +324,7 @@ protected:
// Записываем заданную температуру
if (ot->setHeatingCh1Temp(vars.parameters.heatingSetpoint)) {
currentHeatingTemp = vars.parameters.heatingSetpoint;
heatingSetTempTime = millis();
this->heatingSetTempTime = millis();
} else {
Log.swarningln(FPSTR(S_OT_HEATING), F("Failed set temp"));
@@ -343,15 +343,15 @@ protected:
// только для pid и/или equitherm
if (settings.heating.hysteresis > 0 && !vars.states.emergency && (settings.equitherm.enable || settings.pid.enable)) {
float halfHyst = settings.heating.hysteresis / 2;
if (pump && vars.temperatures.indoor - settings.heating.target + 0.0001 >= halfHyst) {
pump = false;
if (this->pump && vars.temperatures.indoor - settings.heating.target + 0.0001 >= halfHyst) {
this->pump = false;
} else if (!pump && vars.temperatures.indoor - settings.heating.target - 0.0001 <= -(halfHyst)) {
pump = true;
} else if (!this->pump && vars.temperatures.indoor - settings.heating.target - 0.0001 <= -(halfHyst)) {
this->pump = true;
}
} else if (!pump) {
pump = true;
} else if (!this->pump) {
this->pump = true;
}
}
@@ -392,15 +392,15 @@ protected:
}
bool isReady() {
return millis() - startupTime > readyTime;
return millis() - this->startupTime > this->readyTime;
}
bool needSetDhwTemp() {
return millis() - dhwSetTempTime > dhwSetTempInterval;
return millis() - this->dhwSetTempTime > this->dhwSetTempInterval;
}
bool needSetHeatingTemp() {
return millis() - heatingSetTempTime > heatingSetTempInterval;
return millis() - this->heatingSetTempTime > this->heatingSetTempInterval;
}
static void printRequestDetail(OpenThermMessageID id, OpenThermResponseStatus status, unsigned long request, unsigned long response, byte attempt) {

View File

@@ -18,20 +18,44 @@ const char S_SENSORS_BLE[] PROGMEM = "SENSORS.BLE";
class SensorsTask : public LeanTask {
public:
SensorsTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) {}
SensorsTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) {
this->oneWireOutdoorSensor = new OneWire();
this->outdoorSensor = new DallasTemperature(this->oneWireOutdoorSensor);
this->oneWireIndoorSensor = new OneWire();
this->indoorSensor = new DallasTemperature(this->oneWireIndoorSensor);
}
~SensorsTask() {
if (this->outdoorSensor != nullptr) {
delete this->outdoorSensor;
}
if (this->oneWireOutdoorSensor != nullptr) {
delete this->oneWireOutdoorSensor;
}
if (this->indoorSensor != nullptr) {
delete this->indoorSensor;
}
if (this->oneWireIndoorSensor != nullptr) {
delete this->oneWireIndoorSensor;
}
}
protected:
OneWire* oneWireOutdoorSensor;
OneWire* oneWireIndoorSensor;
OneWire* oneWireOutdoorSensor = nullptr;
OneWire* oneWireIndoorSensor = nullptr;
DallasTemperature* outdoorSensor;
DallasTemperature* indoorSensor;
DallasTemperature* outdoorSensor = nullptr;
DallasTemperature* indoorSensor = nullptr;
bool initOutdoorSensor = false;
unsigned long startOutdoorConversionTime = 0;
float filteredOutdoorTemp = 0;
bool emptyOutdoorTemp = true;
bool initIndoorSensor = false;
unsigned long startIndoorConversionTime = 0;
float filteredIndoorTemp = 0;
@@ -123,27 +147,27 @@ protected:
#endif
void outdoorTemperatureSensor() {
if (!initOutdoorSensor) {
oneWireOutdoorSensor = new OneWire(settings.sensors.outdoor.pin);
outdoorSensor = new DallasTemperature(oneWireOutdoorSensor);
outdoorSensor->begin();
outdoorSensor->setResolution(12);
outdoorSensor->setWaitForConversion(false);
outdoorSensor->requestTemperatures();
startOutdoorConversionTime = millis();
initOutdoorSensor = true;
if (!this->initOutdoorSensor) {
this->oneWireOutdoorSensor->begin(settings.sensors.outdoor.pin);
this->outdoorSensor->begin();
this->outdoorSensor->setResolution(12);
this->outdoorSensor->setWaitForConversion(false);
this->outdoorSensor->requestTemperatures();
this->startOutdoorConversionTime = millis();
this->initOutdoorSensor = true;
}
unsigned long estimateConversionTime = millis() - startOutdoorConversionTime;
if (estimateConversionTime < outdoorSensor->millisToWaitForConversion()) {
unsigned long estimateConversionTime = millis() - this->startOutdoorConversionTime;
if (estimateConversionTime < this->outdoorSensor->millisToWaitForConversion()) {
return;
}
bool completed = outdoorSensor->isConversionComplete();
bool completed = this->outdoorSensor->isConversionComplete();
if (!completed && estimateConversionTime >= 1000) {
// fail, retry
outdoorSensor->requestTemperatures();
startOutdoorConversionTime = millis();
this->outdoorSensor->requestTemperatures();
this->startOutdoorConversionTime = millis();
Log.serrorln(FPSTR(S_SENSORS_OUTDOOR), F("Could not read temperature data (no response)"));
}
@@ -152,55 +176,55 @@ protected:
return;
}
float rawTemp = outdoorSensor->getTempCByIndex(0);
float rawTemp = this->outdoorSensor->getTempCByIndex(0);
if (rawTemp == DEVICE_DISCONNECTED_C) {
Log.serrorln(FPSTR(S_SENSORS_OUTDOOR), F("Could not read temperature data (not connected)"));
} else {
Log.straceln(FPSTR(S_SENSORS_OUTDOOR), F("Raw temp: %f"), rawTemp);
if (emptyOutdoorTemp) {
filteredOutdoorTemp = rawTemp;
emptyOutdoorTemp = false;
if (this->emptyOutdoorTemp) {
this->filteredOutdoorTemp = rawTemp;
this->emptyOutdoorTemp = false;
} else {
filteredOutdoorTemp += (rawTemp - filteredOutdoorTemp) * EXT_SENSORS_FILTER_K;
this->filteredOutdoorTemp += (rawTemp - this->filteredOutdoorTemp) * EXT_SENSORS_FILTER_K;
}
filteredOutdoorTemp = floor(filteredOutdoorTemp * 100) / 100;
this->filteredOutdoorTemp = floor(this->filteredOutdoorTemp * 100) / 100;
if (fabs(vars.temperatures.outdoor - filteredOutdoorTemp) > 0.099) {
vars.temperatures.outdoor = filteredOutdoorTemp + settings.sensors.outdoor.offset;
Log.sinfoln(FPSTR(S_SENSORS_OUTDOOR), F("New temp: %f"), filteredOutdoorTemp);
if (fabs(vars.temperatures.outdoor - this->filteredOutdoorTemp) > 0.099) {
vars.temperatures.outdoor = this->filteredOutdoorTemp + settings.sensors.outdoor.offset;
Log.sinfoln(FPSTR(S_SENSORS_OUTDOOR), F("New temp: %f"), this->filteredOutdoorTemp);
}
}
outdoorSensor->requestTemperatures();
startOutdoorConversionTime = millis();
this->outdoorSensor->requestTemperatures();
this->startOutdoorConversionTime = millis();
}
void indoorTemperatureSensor() {
if (!initIndoorSensor) {
oneWireIndoorSensor = new OneWire(settings.sensors.indoor.pin);
indoorSensor = new DallasTemperature(oneWireIndoorSensor);
indoorSensor->begin();
indoorSensor->setResolution(12);
indoorSensor->setWaitForConversion(false);
indoorSensor->requestTemperatures();
startIndoorConversionTime = millis();
initIndoorSensor = true;
if (!this->initIndoorSensor) {
this->oneWireIndoorSensor->begin(settings.sensors.indoor.pin);
this->indoorSensor->begin();
this->indoorSensor->setResolution(12);
this->indoorSensor->setWaitForConversion(false);
this->indoorSensor->requestTemperatures();
this->startIndoorConversionTime = millis();
this->initIndoorSensor = true;
}
unsigned long estimateConversionTime = millis() - startIndoorConversionTime;
if (estimateConversionTime < indoorSensor->millisToWaitForConversion()) {
unsigned long estimateConversionTime = millis() - this->startIndoorConversionTime;
if (estimateConversionTime < this->indoorSensor->millisToWaitForConversion()) {
return;
}
bool completed = indoorSensor->isConversionComplete();
bool completed = this->indoorSensor->isConversionComplete();
if (!completed && estimateConversionTime >= 1000) {
// fail, retry
indoorSensor->requestTemperatures();
startIndoorConversionTime = millis();
this->indoorSensor->requestTemperatures();
this->startIndoorConversionTime = millis();
Log.serrorln(FPSTR(S_SENSORS_INDOOR), F("Could not read temperature data (no response)"));
}
@@ -209,30 +233,30 @@ protected:
return;
}
float rawTemp = indoorSensor->getTempCByIndex(0);
float rawTemp = this->indoorSensor->getTempCByIndex(0);
if (rawTemp == DEVICE_DISCONNECTED_C) {
Log.serrorln(FPSTR(S_SENSORS_INDOOR), F("Could not read temperature data (not connected)"));
} else {
Log.straceln(FPSTR(S_SENSORS_INDOOR), F("Raw temp: %f"), rawTemp);
if (emptyIndoorTemp) {
filteredIndoorTemp = rawTemp;
emptyIndoorTemp = false;
if (this->emptyIndoorTemp) {
this->filteredIndoorTemp = rawTemp;
this->emptyIndoorTemp = false;
} else {
filteredIndoorTemp += (rawTemp - filteredIndoorTemp) * EXT_SENSORS_FILTER_K;
this->filteredIndoorTemp += (rawTemp - this->filteredIndoorTemp) * EXT_SENSORS_FILTER_K;
}
filteredIndoorTemp = floor(filteredIndoorTemp * 100) / 100;
this->filteredIndoorTemp = floor(this->filteredIndoorTemp * 100) / 100;
if (fabs(vars.temperatures.indoor - filteredIndoorTemp) > 0.099) {
vars.temperatures.indoor = filteredIndoorTemp + settings.sensors.indoor.offset;
Log.sinfoln(FPSTR(S_SENSORS_INDOOR), F("New temp: %f"), filteredIndoorTemp);
if (fabs(vars.temperatures.indoor - this->filteredIndoorTemp) > 0.099) {
vars.temperatures.indoor = this->filteredIndoorTemp + settings.sensors.indoor.offset;
Log.sinfoln(FPSTR(S_SENSORS_INDOOR), F("New temp: %f"), this->filteredIndoorTemp);
}
}
indoorSensor->requestTemperatures();
startIndoorConversionTime = millis();
this->indoorSensor->requestTemperatures();
this->startIndoorConversionTime = millis();
}
};

View File

@@ -56,55 +56,7 @@ const char S_WIFI_SETTINGS[] PROGMEM = "WIFI.SETTINGS";
class WifiManagerTask : public LeanTask {
public:
WifiManagerTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) {}
WifiManagerTask* addTaskForDisable(AbstractTask* task) {
this->tasksForDisable.push_back(task);
return this;
}
protected:
bool connected = false;
unsigned long lastArpGratuitous = 0;
unsigned long lastReconnecting = 0;
std::vector<AbstractTask*> tasksForDisable;
const char* getTaskName() {
return "WifiManager";
}
/*int getTaskCore() {
return 1;
}*/
int getTaskPriority() {
return 0;
}
void setup() {
#ifdef WOKWI
WiFi.begin("Wokwi-GUEST", "", 6);
#endif
wm.setDebugOutput(settings.debug, (wm_debuglevel_t) WM_DEBUG_MODE);
wm.setTitle(PROJECT_NAME);
wm.setCustomHeadElement(PSTR(
"<style>"
".bheader + br {display: none;}"
".bheader {margin: 1.25em 0 0.5em 0;padding: 0;border-bottom: 2px solid #000;font-size: 1.5em;}"
"</style>"
));
wm.setCustomMenuHTML(PSTR(
"<style>.wrap h1 {display: none;} .wrap h3 {display: none;} .nh {margin: 0 0 1em 0;} .nh .logo {font-size: 1.8em; margin: 0.5em; text-align: center;} .nh .links {text-align: center;}</style>"
"<div class=\"nh\">"
"<div class=\"logo\">" PROJECT_NAME "</div>"
"<div class=\"links\"><a href=\"" PROJECT_REPO "\" target=\"_blank\">Repo</a> | <a href=\"" PROJECT_REPO "/issues\" target=\"_blank\">Issues</a> | <a href=\"" PROJECT_REPO "/releases\" target=\"_blank\">Releases</a> | <small>v" PROJECT_VERSION " (" __DATE__ ")</small></div>"
"</div>"
));
std::vector<const char *> menu = {"custom", "wifi", "param", "sep", "info", "update", "restart"};
wm.setMenu(menu);
WifiManagerTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) {
wmHostname = new WiFiManagerParameter("hostname", "Hostname", settings.hostname, 80);
wm.addParameter(wmHostname);
@@ -196,10 +148,57 @@ protected:
wmExtPumpAntiStuckTime = new UnsignedShortParameter("ext_pump_as_time", "Anti stuck time", settings.externalPump.antiStuckTime, 5);
wm.addParameter(wmExtPumpAntiStuckTime);
}
WifiManagerTask* addTaskForDisable(AbstractTask* task) {
this->tasksForDisable.push_back(task);
return this;
}
protected:
bool connected = false;
unsigned long lastArpGratuitous = 0;
unsigned long lastReconnecting = 0;
std::vector<AbstractTask*> tasksForDisable;
const char* getTaskName() {
return "WifiManager";
}
/*int getTaskCore() {
return 1;
}*/
int getTaskPriority() {
return 0;
}
void setup() {
#ifdef WOKWI
WiFi.begin("Wokwi-GUEST", "", 6);
#endif
wm.setDebugOutput(settings.debug, (wm_debuglevel_t) WM_DEBUG_MODE);
wm.setTitle(PROJECT_NAME);
wm.setCustomHeadElement(PSTR(
"<style>"
".bheader + br {display: none;}"
".bheader {margin: 1.25em 0 0.5em 0;padding: 0;border-bottom: 2px solid #000;font-size: 1.5em;}"
"</style>"
));
wm.setCustomMenuHTML(PSTR(
"<style>.wrap h1 {display: none;} .wrap h3 {display: none;} .nh {margin: 0 0 1em 0;} .nh .logo {font-size: 1.8em; margin: 0.5em; text-align: center;} .nh .links {text-align: center;}</style>"
"<div class=\"nh\">"
"<div class=\"logo\">" PROJECT_NAME "</div>"
"<div class=\"links\"><a href=\"" PROJECT_REPO "\" target=\"_blank\">Repo</a> | <a href=\"" PROJECT_REPO "/issues\" target=\"_blank\">Issues</a> | <a href=\"" PROJECT_REPO "/releases\" target=\"_blank\">Releases</a> | <small>v" PROJECT_VERSION " (" __DATE__ ")</small></div>"
"</div>"
));
std::vector<const char *> menu = {"custom", "wifi", "param", "sep", "info", "update", "restart"};
wm.setMenu(menu);
//wm.setCleanConnect(true);
wm.setRestorePersistent(false);
wm.setHostname(settings.hostname);
wm.setWiFiAutoReconnect(false);
wm.setAPClientCheck(true);

View File

@@ -1,5 +1,5 @@
#define PROJECT_NAME "OpenTherm Gateway"
#define PROJECT_VERSION "1.4.0-rc.1"
#define PROJECT_VERSION "1.4.0-rc.2"
#define PROJECT_REPO "https://github.com/Laxilef/OTGateway"
#define AP_SSID "OpenTherm Gateway"
#define AP_PASSWORD "otgateway123456"