refactor: memory optimization for esp8266

This commit is contained in:
Yurii
2024-11-11 02:41:39 +03:00
parent 6a9bd9673a
commit fda18cdb13
17 changed files with 1044 additions and 788 deletions

View File

@@ -10,7 +10,8 @@ public:
free(this->buffer);
}
void send(int code, const char* contentType, const JsonVariantConst content, bool pretty = false) {
template <class T>
void send(int code, T contentType, const JsonVariantConst content, bool pretty = false) {
#ifdef ARDUINO_ARCH_ESP8266
if (!this->webServer->chunkedResponseModeStart(code, contentType)) {
this->webServer->send(505, F("text/html"), F("HTTP1.1 required"));

View File

@@ -110,7 +110,7 @@ public:
topic.concat(this->devicePrefix);
topic.concat(nameSeparator);
topic.concat(name);
topic.concat("/config");
topic.concat(F("/config"));
return topic;
}

View File

@@ -37,11 +37,13 @@ const char HA_DEVICE_CLASS[] PROGMEM = "device_class";
const char HA_UNIT_OF_MEASUREMENT[] PROGMEM = "unit_of_measurement";
const char HA_UNIT_OF_MEASUREMENT_C[] PROGMEM = "°C";
const char HA_UNIT_OF_MEASUREMENT_F[] PROGMEM = "°F";
const char HA_UNIT_OF_MEASUREMENT_PERCENT[] PROGMEM = "%";
const char HA_ICON[] PROGMEM = "icon";
const char HA_MIN[] PROGMEM = "min";
const char HA_MAX[] PROGMEM = "max";
const char HA_STEP[] PROGMEM = "step";
const char HA_MODE[] PROGMEM = "mode";
const char HA_MODE_BOX[] PROGMEM = "box";
const char HA_STATE_ON[] PROGMEM = "state_on";
const char HA_STATE_OFF[] PROGMEM = "state_off";
const char HA_PAYLOAD_ON[] PROGMEM = "payload_on";

View File

@@ -61,7 +61,7 @@ public:
}
if (this->cacheHeader != nullptr) {
server.sendHeader("Cache-Control", this->cacheHeader);
server.sendHeader(F("Cache-Control"), this->cacheHeader);
}
#ifdef ARDUINO_ARCH_ESP8266

View File

@@ -8,7 +8,8 @@ public:
typedef std::function<bool(HTTPMethod, const String&)> CanHandleCallback;
typedef std::function<bool()> BeforeSendCallback;
StaticPage(const char* uri, FS* fs, const char* path, const char* cacheHeader = nullptr) {
template <class T>
StaticPage(const char* uri, FS* fs, T path, const char* cacheHeader = nullptr) {
this->uri = uri;
this->fs = fs;
this->path = path;
@@ -55,7 +56,7 @@ public:
this->eTag = esp8266webserver::calcETag(*this->fs, this->path);
}
if (server.header("If-None-Match").equals(this->eTag.c_str())) {
if (server.header(F("If-None-Match")).equals(this->eTag.c_str())) {
server.send(304);
return true;
}
@@ -80,12 +81,12 @@ public:
}
if (this->cacheHeader != nullptr) {
server.sendHeader("Cache-Control", this->cacheHeader);
server.sendHeader(F("Cache-Control"), this->cacheHeader);
}
#if defined(ARDUINO_ARCH_ESP8266)
if (server._eTagEnabled && this->eTag.length() > 0) {
server.sendHeader("ETag", this->eTag);
server.sendHeader(F("ETag"), this->eTag);
}
server.streamFile(file, F("text/html"), method);

View File

@@ -93,10 +93,12 @@ public:
void upload(WebServer& server, const String& uri, HTTPUpload& upload) override {
UpgradeResult* result;
if (upload.name.equals("firmware")) {
if (upload.name.equals(F("firmware"))) {
result = &this->firmwareResult;
} else if (upload.name.equals("filesystem")) {
} else if (upload.name.equals(F("filesystem"))) {
result = &this->filesystemResult;
} else {
return;
}

View File

@@ -59,7 +59,9 @@ build_flags =
upload_speed = 921600
monitor_speed = 115200
;monitor_filters = direct
monitor_filters = esp32_exception_decoder
monitor_filters =
esp32_exception_decoder
esp8266_exception_decoder
board_build.flash_mode = dio
board_build.filesystem = littlefs

View File

@@ -8,6 +8,14 @@ public:
static const char AVAILABILITY_OT_CONN[];
static const char AVAILABILITY_SENSOR_CONN[];
void updateCachedTopics() {
this->statusTopic = this->getDeviceTopic(F("status"));
this->stateTopic = this->getDeviceTopic(F("state"));
this->setStateTopic = this->getDeviceTopic(F("state/set"));
this->settingsTopic = this->getDeviceTopic(F("settings"));
this->setSettingsTopic = this->getDeviceTopic(F("settings/set"));
}
void setExpireAfter(unsigned short value) {
this->expireAfter = value;
}
@@ -60,7 +68,7 @@ public:
case Sensors::Purpose::MODULATION_LEVEL:
doc[FPSTR(HA_DEVICE_CLASS)] = F("power_factor");
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("%");
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
break;
case Sensors::Purpose::CURRENT_POWER:
@@ -80,7 +88,7 @@ public:
case Sensors::Purpose::HUMIDITY:
doc[FPSTR(HA_DEVICE_CLASS)] = F("humidity");
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = "%";
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
break;
default:
@@ -180,7 +188,7 @@ public:
sName += F(" humidity");
doc[FPSTR(HA_DEVICE_CLASS)] = F("humidity");
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = "%";
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
doc[FPSTR(HA_NAME)] = sName;
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.humidity|float(0)|round(2) }}");
break;
@@ -191,7 +199,7 @@ public:
doc[FPSTR(HA_DEVICE_CLASS)] = F("battery");
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = "%";
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
doc[FPSTR(HA_NAME)] = sName;
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.battery|float(0)|round(2) }}");
break;
@@ -213,7 +221,7 @@ public:
} else if (sSensor.type == Sensors::Type::MANUAL) {
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("sensors"), objId.c_str(), F("set"));
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"value\": {{ value }}}");
@@ -245,7 +253,7 @@ public:
);
objId.clear();
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_STATE_CLASS)] = FPSTR(HA_STATE_CLASS_MEASUREMENT);
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
@@ -321,7 +329,7 @@ public:
objId.clear();
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("connectivity");
@@ -371,12 +379,12 @@ public:
objId.clear();
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("signal_strength");
doc[FPSTR(HA_STATE_CLASS)] = FPSTR(HA_STATE_CLASS_MEASUREMENT);
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("%");
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
doc[FPSTR(HA_ICON)] = F("mdi:signal");
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.signalQuality|float(0)|round(0) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
@@ -397,18 +405,18 @@ public:
bool publishSwitchHeatingTurbo(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_turbo"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("heating_turbo"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_NAME)] = F("Turbo heating");
doc[FPSTR(HA_ICON)] = F("mdi:rocket-launch-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_STATE_ON)] = true;
doc[FPSTR(HA_STATE_OFF)] = false;
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.heating.turbo }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"heating\": {\"turbo\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"heating\": {\"turbo\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
@@ -419,10 +427,10 @@ public:
bool publishInputHeatingHysteresis(UnitSystem unit = UnitSystem::METRIC, bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_hysteresis"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("heating_hysteresis"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
@@ -435,14 +443,14 @@ public:
doc[FPSTR(HA_NAME)] = F("Heating hysteresis");
doc[FPSTR(HA_ICON)] = F("mdi:altimeter");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.heating.hysteresis|float(0)|round(2) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"heating\": {\"hysteresis\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0;
doc[FPSTR(HA_MAX)] = 15;
doc[FPSTR(HA_STEP)] = 0.01f;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -451,22 +459,22 @@ public:
bool publishInputHeatingTurboFactor(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_turbo_factor"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("heating_turbo_factor"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("power_factor");
doc[FPSTR(HA_NAME)] = F("Heating turbo factor");
doc[FPSTR(HA_ICON)] = F("mdi:multiplication-box");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.heating.turboFactor|float(0)|round(2) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"heating\": {\"turboFactor\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 1.5;
doc[FPSTR(HA_MAX)] = 10;
doc[FPSTR(HA_STEP)] = 0.01f;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -475,10 +483,10 @@ public:
bool publishInputHeatingMinTemp(UnitSystem unit = UnitSystem::METRIC, bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_min_temp"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("heating_min_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
@@ -495,12 +503,12 @@ public:
doc[FPSTR(HA_NAME)] = F("Heating min temp");
doc[FPSTR(HA_ICON)] = F("mdi:thermometer-chevron-down");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.heating.minTemp|float(0)|round(1) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"heating\": {\"minTemp\" : {{ value }}}}");
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -509,10 +517,10 @@ public:
bool publishInputHeatingMaxTemp(UnitSystem unit = UnitSystem::METRIC, bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_max_temp"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("heating_max_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
@@ -529,12 +537,12 @@ public:
doc[FPSTR(HA_NAME)] = F("Heating max temp");
doc[FPSTR(HA_ICON)] = F("mdi:thermometer-chevron-up");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.heating.maxTemp|float(0)|round(1) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"heating\": {\"maxTemp\" : {{ value }}}}");
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -544,10 +552,10 @@ public:
bool publishInputDhwMinTemp(UnitSystem unit = UnitSystem::METRIC, bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw_min_temp"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("dhw_min_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
@@ -564,12 +572,12 @@ public:
doc[FPSTR(HA_NAME)] = F("DHW min temp");
doc[FPSTR(HA_ICON)] = F("mdi:thermometer-chevron-down");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.dhw.minTemp|float(0)|round(1) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"dhw\": {\"minTemp\" : {{ value }}}}");
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -578,10 +586,10 @@ public:
bool publishInputDhwMaxTemp(UnitSystem unit = UnitSystem::METRIC, bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw_max_temp"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("dhw_max_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
@@ -598,12 +606,12 @@ public:
doc[FPSTR(HA_NAME)] = F("DHW max temp");
doc[FPSTR(HA_ICON)] = F("mdi:thermometer-chevron-up");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.dhw.maxTemp|float(0)|round(1) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"dhw\": {\"maxTemp\" : {{ value }}}}");
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -613,20 +621,20 @@ public:
bool publishSwitchPid(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("pid"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_NAME)] = F("PID");
doc[FPSTR(HA_ICON)] = F("mdi:chart-bar-stacked");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_STATE_ON)] = true;
doc[FPSTR(HA_STATE_OFF)] = false;
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.enabled }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"pid\": {\"enable\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"pid\": {\"enable\" : false}}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"pid\": {\"enabled\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"pid\": {\"enabled\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -635,21 +643,21 @@ public:
bool publishInputPidFactorP(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_p"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("pid_p"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_NAME)] = F("PID factor P");
doc[FPSTR(HA_ICON)] = F("mdi:alpha-p-circle-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.p_factor|float(0)|round(3) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"pid\": {\"p_factor\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0.1f;
doc[FPSTR(HA_MAX)] = 1000;
doc[FPSTR(HA_STEP)] = 0.1f;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -658,21 +666,21 @@ public:
bool publishInputPidFactorI(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_i"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("pid_i"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_NAME)] = F("PID factor I");
doc[FPSTR(HA_ICON)] = F("mdi:alpha-i-circle-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.i_factor|float(0)|round(4) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"pid\": {\"i_factor\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0;
doc[FPSTR(HA_MAX)] = 100;
doc[FPSTR(HA_STEP)] = 0.001f;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -681,21 +689,21 @@ public:
bool publishInputPidFactorD(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_d"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("pid_d"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_NAME)] = F("PID factor D");
doc[FPSTR(HA_ICON)] = F("mdi:alpha-d-circle-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.d_factor|float(0)|round(3) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"pid\": {\"d_factor\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0;
doc[FPSTR(HA_MAX)] = 100000;
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -704,23 +712,23 @@ public:
bool publishInputPidDt(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_dt"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("pid_dt"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("duration");
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("s");
doc[FPSTR(HA_NAME)] = F("PID DT");
doc[FPSTR(HA_ICON)] = F("mdi:timer-cog-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.dt|int(0) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"pid\": {\"dt\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 30;
doc[FPSTR(HA_MAX)] = 1800;
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -729,10 +737,10 @@ public:
bool publishInputPidMinTemp(UnitSystem unit = UnitSystem::METRIC, bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_min_temp"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("pid_min_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
@@ -749,12 +757,12 @@ public:
doc[FPSTR(HA_NAME)] = F("PID min temp");
doc[FPSTR(HA_ICON)] = F("mdi:thermometer-chevron-down");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.minTemp|float(0)|round(1) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"pid\": {\"minTemp\" : {{ value }}}}");
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -763,10 +771,10 @@ public:
bool publishInputPidMaxTemp(UnitSystem unit = UnitSystem::METRIC, bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_max_temp"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("pid_max_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
@@ -783,12 +791,12 @@ public:
doc[FPSTR(HA_NAME)] = F("PID max temp");
doc[FPSTR(HA_ICON)] = F("mdi:thermometer-chevron-up");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.maxTemp|float(0)|round(1) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"pid\": {\"maxTemp\" : {{ value }}}}");
doc[FPSTR(HA_STEP)] = 1;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -798,20 +806,20 @@ public:
bool publishSwitchEquitherm(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("equitherm"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_NAME)] = F("Equitherm");
doc[FPSTR(HA_ICON)] = F("mdi:sun-snowflake-variant");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_STATE_ON)] = true;
doc[FPSTR(HA_STATE_OFF)] = false;
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.equitherm.enabled }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"equitherm\": {\"enable\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"equitherm\": {\"enable\" : false}}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_PAYLOAD_ON)] = F("{\"equitherm\": {\"enabled\" : true}}");
doc[FPSTR(HA_PAYLOAD_OFF)] = F("{\"equitherm\": {\"enabled\" : false}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -820,21 +828,21 @@ public:
bool publishInputEquithermFactorN(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm_n"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("equitherm_n"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_NAME)] = F("Equitherm factor N");
doc[FPSTR(HA_ICON)] = F("mdi:alpha-n-circle-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.equitherm.n_factor|float(0)|round(3) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"equitherm\": {\"n_factor\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0.001f;
doc[FPSTR(HA_MAX)] = 10;
doc[FPSTR(HA_STEP)] = 0.001f;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -843,21 +851,21 @@ public:
bool publishInputEquithermFactorK(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm_k"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("equitherm_k"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_NAME)] = F("Equitherm factor K");
doc[FPSTR(HA_ICON)] = F("mdi:alpha-k-circle-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.equitherm.k_factor|float(0)|round(2) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"equitherm\": {\"k_factor\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0;
doc[FPSTR(HA_MAX)] = 10;
doc[FPSTR(HA_STEP)] = 0.01f;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -866,24 +874,24 @@ public:
bool publishInputEquithermFactorT(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.pid.enable, 'offline', 'online') }}");
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.pid.enabled, 'offline', 'online') }}");
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm_t"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("equitherm_t"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_NAME)] = F("Equitherm factor T");
doc[FPSTR(HA_ICON)] = F("mdi:alpha-t-circle-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.equitherm.t_factor|float(0)|round(2) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"equitherm\": {\"t_factor\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0;
doc[FPSTR(HA_MAX)] = 10;
doc[FPSTR(HA_STEP)] = 0.01f;
doc[FPSTR(HA_MODE)] = "box";
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -895,12 +903,12 @@ public:
JsonDocument doc;
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("status"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("status"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("problem");
doc[FPSTR(HA_NAME)] = F("Status");
doc[FPSTR(HA_ICON)] = F("mdi:list-status");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_STATE_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value == 'online', 'OFF', 'ON') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = 60;
doc.shrinkToFit();
@@ -910,15 +918,15 @@ public:
bool publishEmergencyState(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("emergency"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("emergency"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("problem");
doc[FPSTR(HA_NAME)] = F("Emergency");
doc[FPSTR(HA_ICON)] = F("mdi:alert-rhombus-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.master.emergency.state, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -928,15 +936,15 @@ public:
bool publishOpenthermConnectedState(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("ot_status"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("ot_status"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("connectivity");
doc[FPSTR(HA_NAME)] = F("Opentherm status");
doc[FPSTR(HA_ICON)] = F("mdi:list-status");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.connected, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -946,18 +954,18 @@ public:
bool publishHeatingState(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_OT_CONN;
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("heating"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
//doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("running");
doc[FPSTR(HA_NAME)] = F("Heating");
doc[FPSTR(HA_ICON)] = F("mdi:radiator");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.heating.active, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -967,18 +975,18 @@ public:
bool publishDhwState(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_OT_CONN;
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("dhw"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
//doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("running");
doc[FPSTR(HA_NAME)] = F("DHW");
doc[FPSTR(HA_ICON)] = F("mdi:faucet");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.dhw.active, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -988,18 +996,18 @@ public:
bool publishFlameState(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_OT_CONN;
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("flame"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("flame"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
//doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("running");
doc[FPSTR(HA_NAME)] = F("Flame");
doc[FPSTR(HA_ICON)] = F("mdi:gas-burner");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.flame, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1009,18 +1017,18 @@ public:
bool publishFaultState(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_OT_CONN;
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("fault"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("fault"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("problem");
doc[FPSTR(HA_NAME)] = F("Fault");
doc[FPSTR(HA_ICON)] = F("mdi:alert-remove-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.fault.active, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1030,18 +1038,18 @@ public:
bool publishDiagState(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_OT_CONN;
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("problem");
doc[FPSTR(HA_NAME)] = F("Diagnostic");
doc[FPSTR(HA_ICON)] = F("mdi:account-wrench");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.diag.active, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1051,15 +1059,15 @@ public:
bool publishExternalPumpState(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("ext_pump"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("ext_pump"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("running");
doc[FPSTR(HA_NAME)] = F("External pump");
doc[FPSTR(HA_ICON)] = F("mdi:pump");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.master.externalPump.state, 'ON', 'OFF') }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1069,17 +1077,17 @@ public:
bool publishFaultCode(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.opentherm.connected and value_json.fault.active, 'online', 'offline') }}");
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.connected and value_json.slave.fault.active, 'online', 'offline') }}");
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("fault_code"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("fault_code"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_NAME)] = F("Fault code");
doc[FPSTR(HA_ICON)] = F("mdi:cog-box");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ \"%02d (0x%02X)\"|format(value_json.slave.fault.code, value_json.slave.fault.code) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1089,17 +1097,17 @@ public:
bool publishDiagCode(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.opentherm.connected and value_json.fault.active or value_json.diag.active, 'online', 'offline') }}");
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.connected and value_json.slave.fault.active or value_json.slave.diag.active, 'online', 'offline') }}");
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("diagnostic_code"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("diagnostic_code"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_NAME)] = F("Diagnostic code");
doc[FPSTR(HA_ICON)] = F("mdi:information-box");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ \"%02d (0x%02X)\"|format(value_json.slave.diag.code, value_json.slave.diag.code) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1109,17 +1117,17 @@ public:
bool publishNetworkRssi(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("rssi"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("rssi"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("signal_strength");
doc[FPSTR(HA_STATE_CLASS)] = FPSTR(HA_STATE_CLASS_MEASUREMENT);
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("dBm");
doc[FPSTR(HA_NAME)] = F("RSSI");
doc[FPSTR(HA_ICON)] = F("mdi:signal");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.master.network.rssi|float(0)|round(1) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1129,17 +1137,17 @@ public:
bool publishUptime(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("uptime"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("uptime"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("duration");
doc[FPSTR(HA_STATE_CLASS)] = F("total_increasing");
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("s");
doc[FPSTR(HA_NAME)] = F("Uptime");
doc[FPSTR(HA_ICON)] = F("mdi:clock-start");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_STATE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.master.uptime|int(0) }}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1150,20 +1158,20 @@ public:
bool publishClimateHeating(UnitSystem unit = UnitSystem::METRIC, byte minTemp = 20, byte maxTemp = 90, bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("heating"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_NAME)] = F("Heating");
doc[FPSTR(HA_ICON)] = F("mdi:radiator");
doc[FPSTR(HA_CURRENT_TEMPERATURE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_CURRENT_TEMPERATURE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_CURRENT_TEMPERATURE_TEMPLATE)] = F("{{ iif(value_json.master.heating.indoorTempControl, value_json.master.heating.indoorTemp, value_json.master.heating.currentTemp, 0)|float(0)|round(2) }}");
doc[FPSTR(HA_TEMPERATURE_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_TEMPERATURE_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_TEMPERATURE_COMMAND_TEMPLATE)] = F("{\"heating\": {\"target\" : {{ value }}}}");
doc[FPSTR(HA_TEMPERATURE_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_TEMPERATURE_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_TEMPERATURE_STATE_TEMPLATE)] = F("{{ value_json.heating.target|float(0)|round(1) }}");
if (unit == UnitSystem::METRIC) {
@@ -1173,21 +1181,21 @@ public:
doc[FPSTR(HA_TEMPERATURE_UNIT)] = "F";
}
doc[FPSTR(HA_MODE_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_MODE_COMMAND_TEMPLATE)] = F("{% if value == 'heat' %}{\"heating\": {\"enable\" : true}}"
"{% elif value == 'off' %}{\"heating\": {\"enable\" : false}}{% endif %}");
doc[FPSTR(HA_MODE_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_MODE_STATE_TEMPLATE)] = F("{{ iif(value_json.heating.enable, 'heat', 'off') }}");
doc[FPSTR(HA_MODE_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_MODE_COMMAND_TEMPLATE)] = F("{% if value == 'heat' %}{\"heating\": {\"enabled\" : true}}"
"{% elif value == 'off' %}{\"heating\": {\"enabled\" : false}}{% endif %}");
doc[FPSTR(HA_MODE_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_MODE_STATE_TEMPLATE)] = F("{{ iif(value_json.heating.enabled, 'heat', 'off') }}");
doc[FPSTR(HA_MODES)][0] = F("off");
doc[FPSTR(HA_MODES)][1] = F("heat");
doc[FPSTR(HA_ACTION_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_ACTION_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_ACTION_TEMPLATE)] = F("{{ iif(value_json.master.heating.enabled, iif(value_json.slave.heating.active, 'heating', 'idle'), 'off') }}");
doc[FPSTR(HA_PRESET_MODE_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_PRESET_MODE_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_PRESET_MODE_COMMAND_TEMPLATE)] = F("{% if value == 'boost' %}{\"heating\": {\"turbo\" : true}}"
"{% elif value == 'none' %}{\"heating\": {\"turbo\" : false}}{% endif %}");
doc[FPSTR(HA_PRESET_MODE_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_PRESET_MODE_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_PRESET_MODE_VALUE_TEMPLATE)] = F("{{ iif(value_json.heating.turbo, 'boost', 'none') }}");
doc[FPSTR(HA_PRESET_MODES)][0] = F("boost");
@@ -1202,20 +1210,20 @@ public:
bool publishClimateDhw(UnitSystem unit = UnitSystem::METRIC, byte minTemp = 40, byte maxTemp = 60, bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("dhw"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_NAME)] = F("DHW");
doc[FPSTR(HA_ICON)] = F("mdi:faucet");
doc[FPSTR(HA_CURRENT_TEMPERATURE_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_CURRENT_TEMPERATURE_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_CURRENT_TEMPERATURE_TEMPLATE)] = F("{{ value_json.master.dhw.currentTemp|float(0)|round(1) }}");
doc[FPSTR(HA_TEMPERATURE_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_TEMPERATURE_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_TEMPERATURE_COMMAND_TEMPLATE)] = F("{\"dhw\": {\"target\" : {{ value|int(0) }}}}");
doc[FPSTR(HA_TEMPERATURE_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_TEMPERATURE_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_TEMPERATURE_STATE_TEMPLATE)] = F("{{ value_json.dhw.target|float(0)|round(1) }}");
if (unit == UnitSystem::METRIC) {
@@ -1225,15 +1233,15 @@ public:
doc[FPSTR(HA_TEMPERATURE_UNIT)] = "F";
}
doc[FPSTR(HA_MODE_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_MODE_COMMAND_TEMPLATE)] = F("{% if value == 'heat' %}{\"dhw\": {\"enable\" : true}}"
"{% elif value == 'off' %}{\"dhw\": {\"enable\" : false}}{% endif %}");
doc[FPSTR(HA_MODE_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_MODE_STATE_TEMPLATE)] = F("{{ iif(value_json.dhw.enable, 'heat', 'off') }}");
doc[FPSTR(HA_MODE_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_MODE_COMMAND_TEMPLATE)] = F("{% if value == 'heat' %}{\"dhw\": {\"enabled\" : true}}"
"{% elif value == 'off' %}{\"dhw\": {\"enabled\" : false}}{% endif %}");
doc[FPSTR(HA_MODE_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_MODE_STATE_TEMPLATE)] = F("{{ iif(value_json.dhw.enabled, 'heat', 'off') }}");
doc[FPSTR(HA_MODES)][0] = F("off");
doc[FPSTR(HA_MODES)][1] = F("heat");
doc[FPSTR(HA_ACTION_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_ACTION_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_ACTION_TEMPLATE)] = F("{{ iif(value_json.master.dhw.enabled, iif(value_json.slave.dhw.active, 'heating', 'idle'), 'off') }}");
doc[FPSTR(HA_MIN_TEMP)] = minTemp;
@@ -1247,14 +1255,14 @@ public:
bool publishRestartButton(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("restart"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("restart"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("restart");
doc[FPSTR(HA_NAME)] = F("Restart");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("state/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setStateTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"actions\": {\"restart\": true}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1264,17 +1272,17 @@ public:
bool publishResetFaultButton(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.fault.active, 'online', 'offline') }}");
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.fault.active, 'online', 'offline') }}");
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("reset_fault"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("reset_fault"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("restart");
doc[FPSTR(HA_NAME)] = F("Reset fault");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("state/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setStateTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"actions\": {\"resetFault\": true}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1284,17 +1292,17 @@ public:
bool publishResetDiagButton(bool enabledByDefault = true) {
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("status"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->getDeviceTopic(F("state"));
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.diag.active, 'online', 'offline') }}");
doc[FPSTR(HA_AVAILABILITY)][0][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = this->stateTopic.c_str();
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.diag.active, 'online', 'offline') }}");
doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all");
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("reset_diagnostic"));
doc[FPSTR(HA_OBJECT_ID)] = this->getObjectIdWithPrefix(F("reset_diagnostic"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("restart");
doc[FPSTR(HA_NAME)] = F("Reset diagnostic");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("state/set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setStateTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"actions\": {\"resetDiagnostic\": true}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
@@ -1334,6 +1342,7 @@ public:
protected:
unsigned short expireAfter = 300u;
String statusTopic, stateTopic, setStateTopic, settingsTopic, setSettingsTopic;
};
const char HaHelper::AVAILABILITY_OT_CONN[] = "{{ iif(value_json.slave.connected, 'online', 'offline') }}";

View File

@@ -517,7 +517,7 @@ protected:
if (configuredGpio == GPIO_IS_NOT_CONFIGURED) {
if (vars.externalPump.state) {
vars.externalPump.state = false;
vars.externalPump.lastEnableTime = millis();
vars.externalPump.lastEnabledTime = millis();
Log.sinfoln(FPSTR(L_EXTPUMP), F("Disabled: use = off"));
}
@@ -538,7 +538,7 @@ protected:
digitalWrite(configuredGpio, LOW);
vars.externalPump.state = false;
vars.externalPump.lastEnableTime = millis();
vars.externalPump.lastEnabledTime = millis();
Log.sinfoln(FPSTR(L_EXTPUMP), F("Disabled: use = off"));
}
@@ -551,7 +551,7 @@ protected:
digitalWrite(configuredGpio, LOW);
vars.externalPump.state = false;
vars.externalPump.lastEnableTime = millis();
vars.externalPump.lastEnabledTime = millis();
Log.sinfoln(FPSTR(L_EXTPUMP), F("Disabled: expired post circulation time"));
@@ -559,7 +559,7 @@ protected:
digitalWrite(configuredGpio, LOW);
vars.externalPump.state = false;
vars.externalPump.lastEnableTime = millis();
vars.externalPump.lastEnabledTime = millis();
Log.sinfoln(FPSTR(L_EXTPUMP), F("Disabled: expired anti stuck time"));
}
@@ -576,7 +576,7 @@ protected:
Log.sinfoln(FPSTR(L_EXTPUMP), F("Enabled: heating on"));
} else if (!vars.externalPump.state && (vars.externalPump.lastEnableTime == 0 || millis() - vars.externalPump.lastEnableTime >= (settings.externalPump.antiStuckInterval * 1000ul))) {
} else if (!vars.externalPump.state && (vars.externalPump.lastEnabledTime == 0 || millis() - vars.externalPump.lastEnabledTime >= (settings.externalPump.antiStuckInterval * 1000lu))) {
vars.externalPump.state = true;
this->externalPumpStartTime = millis();
this->extPumpStartReason = MainTask::PumpStartReason::ANTISTUCK;

View File

@@ -192,6 +192,7 @@ protected:
Log.sinfoln(FPSTR(L_MQTT), F("Connecting to %s:%u..."), settings.mqtt.server, settings.mqtt.port);
this->haHelper->setDevicePrefix(settings.mqtt.prefix);
this->haHelper->updateCachedTopics();
this->client->stop();
this->client->setId(networkSettings.hostname);
this->client->setUsernamePassword(settings.mqtt.user, settings.mqtt.password);
@@ -221,14 +222,14 @@ protected:
// publish variables and status
if (this->newConnection || millis() - this->prevPubVarsTime > (settings.mqtt.interval * 1000u)) {
this->writer->publish(this->haHelper->getDeviceTopic("status").c_str(), "online", false);
this->publishVariables(this->haHelper->getDeviceTopic("state").c_str());
this->writer->publish(this->haHelper->getDeviceTopic(F("status")).c_str(), "online", false);
this->publishVariables(this->haHelper->getDeviceTopic(F("state")).c_str());
this->prevPubVarsTime = millis();
}
// publish settings
if (this->newConnection || millis() - this->prevPubSettingsTime > (settings.mqtt.interval * 10000u)) {
this->publishSettings(this->haHelper->getDeviceTopic("settings").c_str());
this->publishSettings(this->haHelper->getDeviceTopic(F("settings")).c_str());
this->prevPubSettingsTime = millis();
}
@@ -292,7 +293,7 @@ protected:
case Sensors::Type::MANUAL: {
String topic = this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(prevSettings.name),
Sensors::makeObjectId(prevSettings.name).c_str(),
F("set")
);
this->client->unsubscribe(topic.c_str());
@@ -328,7 +329,7 @@ protected:
case Sensors::Type::MANUAL: {
String topic = this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(prevSettings.name),
Sensors::makeObjectId(prevSettings.name).c_str(),
F("set")
);
this->client->subscribe(topic.c_str());
@@ -355,15 +356,15 @@ protected:
unsigned long downtime = (millis() - this->disconnectedTime) / 1000;
Log.sinfoln(FPSTR(L_MQTT), F("Connected (downtime: %u s.)"), downtime);
this->client->subscribe(this->haHelper->getDeviceTopic("settings/set").c_str());
this->client->subscribe(this->haHelper->getDeviceTopic("state/set").c_str());
this->client->subscribe(this->haHelper->getDeviceTopic(F("settings/set")).c_str());
this->client->subscribe(this->haHelper->getDeviceTopic(F("state/set")).c_str());
}
void onDisconnect() {
this->disconnectedTime = millis();
unsigned long uptime = (millis() - this->connectedTime) / 1000;
Log.swarningln(FPSTR(L_MQTT), F("Disconnected (reason: %d uptime: %u s.)"), this->client->connectError(), uptime);
Log.swarningln(FPSTR(L_MQTT), F("Disconnected (reason: %d uptime: %lu s.)"), this->client->connectError(), uptime);
}
void onMessage(const char* topic, uint8_t* payload, size_t length) {
@@ -380,12 +381,12 @@ protected:
} else if (payload[i] == 13) {
continue;
} else if (payload[i] == 10) {
Log.print("\r\n> ");
Log.print(F("\r\n> "));
} else {
Log.print((char) payload[i]);
}
}
Log.print("\r\n\n");
Log.print(F("\r\n\n"));
Log.flush();
Log.unlock();
}
@@ -403,14 +404,14 @@ protected:
}
doc.shrinkToFit();
if (this->haHelper->getDeviceTopic("state/set").equals(topic)) {
if (this->haHelper->getDeviceTopic(F("state/set")).equals(topic)) {
this->writer->publish(topic, nullptr, 0, true);
if (jsonToVars(doc, vars)) {
this->resetPublishedVarsTime();
}
} else if (this->haHelper->getDeviceTopic("settings/set").equals(topic)) {
} else if (this->haHelper->getDeviceTopic(F("settings/set")).equals(topic)) {
this->writer->publish(topic, nullptr, 0, true);
if (safeJsonToSettings(doc, settings)) {
@@ -422,10 +423,10 @@ protected:
this->writer->publish(topic, nullptr, 0, true);
String _topic = topic;
String sensorsTopic = this->haHelper->getDeviceTopic("sensors/");
unsigned short stLength = sensorsTopic.length();
String sensorsTopic = this->haHelper->getDeviceTopic(F("sensors/"));
auto stLength = sensorsTopic.length();
if (_topic.startsWith(sensorsTopic) && _topic.endsWith("/set")) {
if (_topic.startsWith(sensorsTopic) && _topic.endsWith(F("/set"))) {
if (_topic.length() > stLength + 4) {
String name = _topic.substring(stLength, _topic.indexOf('/', stLength));
int16_t id = Sensors::getIdByObjectId(name.c_str());
@@ -512,7 +513,7 @@ protected:
case Sensors::Type::MANUAL: {
String topic = this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(sSettings.name),
Sensors::makeObjectId(sSettings.name).c_str(),
F("set")
);
this->client->subscribe(topic.c_str());
@@ -597,8 +598,11 @@ protected:
sensorResultToJson(sensorId, doc);
doc.shrinkToFit();
String objId = Sensors::makeObjectId(sSettings.name);
String topic = this->haHelper->getDeviceTopic(F("sensors"), objId);
String topic = this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(sSettings.name).c_str()
);
return this->writer->publish(topic.c_str(), doc, true);
}

View File

@@ -244,13 +244,13 @@ protected:
if (vars.master.heating.enabled != vars.slave.heating.enabled) {
this->prevUpdateNonEssentialVars = 0;
vars.slave.heating.enabled = vars.master.heating.enabled;
Log.sinfoln(FPSTR(L_OT_HEATING), "%s", vars.master.heating.enabled ? F("Enabled") : F("Disabled"));
Log.sinfoln(FPSTR(L_OT_HEATING), vars.master.heating.enabled ? F("Enabled") : F("Disabled"));
}
if (vars.master.dhw.enabled != vars.slave.dhw.enabled) {
this->prevUpdateNonEssentialVars = 0;
vars.slave.dhw.enabled = vars.master.heating.enabled;
Log.sinfoln(FPSTR(L_OT_DHW), "%s", vars.master.heating.enabled ? F("Enabled") : F("Disabled"));
Log.sinfoln(FPSTR(L_OT_DHW), vars.master.heating.enabled ? F("Enabled") : F("Disabled"));
}
vars.slave.heating.active = CustomOpenTherm::isCentralHeatingActive(response);

View File

@@ -88,10 +88,10 @@ protected:
return result;
});
this->webServer->addHandler(indexPage);*/
this->webServer->addHandler(new StaticPage("/", &LittleFS, "/pages/index.html", PORTAL_CACHE));
this->webServer->addHandler(new StaticPage("/", &LittleFS, F("/pages/index.html"), PORTAL_CACHE));
// dashboard page
auto dashboardPage = (new StaticPage("/dashboard.html", &LittleFS, "/pages/dashboard.html", PORTAL_CACHE))
auto dashboardPage = (new StaticPage("/dashboard.html", &LittleFS, F("/pages/dashboard.html"), PORTAL_CACHE))
->setBeforeSendCallback([this]() {
if (this->isAuthRequired() && !this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
this->webServer->requestAuthentication(DIGEST_AUTH);
@@ -103,7 +103,7 @@ protected:
this->webServer->addHandler(dashboardPage);
// restart
this->webServer->on("/restart.html", HTTP_GET, [this]() {
this->webServer->on(F("/restart.html"), HTTP_GET, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
this->webServer->send(401);
@@ -112,12 +112,12 @@ protected:
}
vars.actions.restart = true;
this->webServer->sendHeader("Location", "/");
this->webServer->sendHeader(F("Location"), "/");
this->webServer->send(302);
});
// network settings page
auto networkPage = (new StaticPage("/network.html", &LittleFS, "/pages/network.html", PORTAL_CACHE))
auto networkPage = (new StaticPage("/network.html", &LittleFS, F("/pages/network.html"), PORTAL_CACHE))
->setBeforeSendCallback([this]() {
if (this->isAuthRequired() && !this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
this->webServer->requestAuthentication(DIGEST_AUTH);
@@ -129,7 +129,7 @@ protected:
this->webServer->addHandler(networkPage);
// settings page
auto settingsPage = (new StaticPage("/settings.html", &LittleFS, "/pages/settings.html", PORTAL_CACHE))
auto settingsPage = (new StaticPage("/settings.html", &LittleFS, F("/pages/settings.html"), PORTAL_CACHE))
->setBeforeSendCallback([this]() {
if (this->isAuthRequired() && !this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
this->webServer->requestAuthentication(DIGEST_AUTH);
@@ -141,7 +141,7 @@ protected:
this->webServer->addHandler(settingsPage);
// sensors page
auto sensorsPage = (new StaticPage("/sensors.html", &LittleFS, "/pages/sensors.html", PORTAL_CACHE))
auto sensorsPage = (new StaticPage("/sensors.html", &LittleFS, F("/pages/sensors.html"), PORTAL_CACHE))
->setBeforeSendCallback([this]() {
if (this->isAuthRequired() && !this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
this->webServer->requestAuthentication(DIGEST_AUTH);
@@ -153,7 +153,7 @@ protected:
this->webServer->addHandler(sensorsPage);
// upgrade page
auto upgradePage = (new StaticPage("/upgrade.html", &LittleFS, "/pages/upgrade.html", PORTAL_CACHE))
auto upgradePage = (new StaticPage("/upgrade.html", &LittleFS, F("/pages/upgrade.html"), PORTAL_CACHE))
->setBeforeSendCallback([this]() {
if (this->isAuthRequired() && !this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
this->webServer->requestAuthentication(DIGEST_AUTH);
@@ -167,7 +167,7 @@ protected:
// OTA
auto upgradeHandler = (new UpgradeHandler("/api/upgrade"))->setCanUploadCallback([this](const String& uri) {
if (this->isAuthRequired() && !this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
this->webServer->sendHeader("Connection", "close");
this->webServer->sendHeader(F("Connection"), F("close"));
this->webServer->send(401);
return false;
}
@@ -184,22 +184,22 @@ protected:
status = 400;
}
String response = "{\"firmware\": {\"status\": ";
String response = F("{\"firmware\": {\"status\": ");
response.concat((short int) fwResult.status);
response.concat(", \"error\": \"");
response.concat(F(", \"error\": \""));
response.concat(fwResult.error);
response.concat("\"}, \"filesystem\": {\"status\": ");
response.concat(F("\"}, \"filesystem\": {\"status\": "));
response.concat((short int) fsResult.status);
response.concat(", \"error\": \"");
response.concat(F(", \"error\": \""));
response.concat(fsResult.error);
response.concat("\"}}");
this->webServer->send(status, "application/json", response);
response.concat(F("\"}}"));
this->webServer->send(status, F("application/json"), response);
});
this->webServer->addHandler(upgradeHandler);
// backup
this->webServer->on("/api/backup/save", HTTP_GET, [this]() {
this->webServer->on(F("/api/backup/save"), HTTP_GET, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
return this->webServer->send(401);
@@ -208,24 +208,24 @@ protected:
JsonDocument doc;
auto networkDoc = doc["network"].to<JsonObject>();
auto networkDoc = doc[FPSTR(S_NETWORK)].to<JsonObject>();
networkSettingsToJson(networkSettings, networkDoc);
auto settingskDoc = doc["settings"].to<JsonObject>();
settingsToJson(settings, settingskDoc);
auto settingsDoc = doc[FPSTR(S_SETTINGS)].to<JsonObject>();
settingsToJson(settings, settingsDoc);
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
auto sensorSettingskDoc = doc["sensors"][sensorId].to<JsonObject>();
sensorSettingsToJson(sensorId, Sensors::settings[sensorId], sensorSettingskDoc);
auto sensorsettingsDoc = doc[FPSTR(S_SENSORS)][sensorId].to<JsonObject>();
sensorSettingsToJson(sensorId, Sensors::settings[sensorId], sensorsettingsDoc);
}
doc.shrinkToFit();
this->webServer->sendHeader(F("Content-Disposition"), F("attachment; filename=\"backup.json\""));
this->bufferedWebServer->send(200, "application/json", doc);
this->bufferedWebServer->send(200, F("application/json"), doc);
});
this->webServer->on("/api/backup/restore", HTTP_POST, [this]() {
this->webServer->on(F("/api/backup/restore"), HTTP_POST, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
return this->webServer->send(401);
@@ -254,13 +254,13 @@ protected:
}
bool changed = false;
if (!doc["settings"].isNull() && jsonToSettings(doc["settings"], settings)) {
if (!doc[FPSTR(S_SETTINGS)].isNull() && jsonToSettings(doc[FPSTR(S_SETTINGS)], settings)) {
vars.actions.restart = true;
fsSettings.update();
changed = true;
}
if (!doc["network"].isNull() && jsonToNetworkSettings(doc["network"], networkSettings)) {
if (!doc[FPSTR(S_NETWORK)].isNull() && jsonToNetworkSettings(doc[FPSTR(S_NETWORK)], networkSettings)) {
fsNetworkSettings.update();
network->setHostname(networkSettings.hostname)
->setStaCredentials(networkSettings.sta.ssid, networkSettings.sta.password, networkSettings.sta.channel)
@@ -276,13 +276,13 @@ protected:
changed = true;
}
if (!doc["sensors"].isNull()) {
if (!doc[FPSTR(S_SENSORS)].isNull()) {
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
if (doc["sensors"][sensorId].isNull()) {
if (doc[FPSTR(S_SENSORS)][sensorId].isNull()) {
continue;
}
auto sensorSettingsDoc = doc["sensors"][sensorId].to<JsonObject>();
auto sensorSettingsDoc = doc[FPSTR(S_SENSORS)][sensorId].to<JsonObject>();
if (jsonToSensorSettings(sensorId, sensorSettingsDoc, Sensors::settings[sensorId])){
changed = true;
}
@@ -296,7 +296,7 @@ protected:
});
// network
this->webServer->on("/api/network/settings", HTTP_GET, [this]() {
this->webServer->on(F("/api/network/settings"), HTTP_GET, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
return this->webServer->send(401);
@@ -307,10 +307,10 @@ protected:
networkSettingsToJson(networkSettings, doc);
doc.shrinkToFit();
this->bufferedWebServer->send(200, "application/json", doc);
this->bufferedWebServer->send(200, F("application/json"), doc);
});
this->webServer->on("/api/network/settings", HTTP_POST, [this]() {
this->webServer->on(F("/api/network/settings"), HTTP_POST, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
return this->webServer->send(401);
@@ -345,7 +345,7 @@ protected:
networkSettingsToJson(networkSettings, doc);
doc.shrinkToFit();
this->bufferedWebServer->send(changed ? 201 : 200, "application/json", doc);
this->bufferedWebServer->send(changed ? 201 : 200, F("application/json"), doc);
if (changed) {
doc.clear();
@@ -366,7 +366,7 @@ protected:
}
});
this->webServer->on("/api/network/scan", HTTP_GET, [this]() {
this->webServer->on(F("/api/network/scan"), HTTP_GET, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
this->webServer->send(401);
@@ -391,28 +391,28 @@ protected:
JsonDocument doc;
for (short int i = 0; i < apCount; i++) {
String ssid = WiFi.SSID(i);
doc[i]["ssid"] = ssid;
doc[i]["bssid"] = WiFi.BSSIDstr(i);
doc[i]["signalQuality"] = NetworkMgr::rssiToSignalQuality(WiFi.RSSI(i));
doc[i]["channel"] = WiFi.channel(i);
doc[i]["hidden"] = !ssid.length();
doc[i][FPSTR(S_SSID)] = ssid;
doc[i][FPSTR(S_BSSID)] = WiFi.BSSIDstr(i);
doc[i][FPSTR(S_SIGNAL_QUALITY)] = NetworkMgr::rssiToSignalQuality(WiFi.RSSI(i));
doc[i][FPSTR(S_CHANNEL)] = WiFi.channel(i);
doc[i][FPSTR(S_HIDDEN)] = !ssid.length();
#ifdef ARDUINO_ARCH_ESP8266
const bss_info* info = WiFi.getScanInfoByIndex(i);
doc[i]["auth"] = info->authmode;
doc[i][FPSTR(S_AUTH)] = info->authmode;
#else
doc[i]["auth"] = WiFi.encryptionType(i);
doc[i][FPSTR(S_AUTH)] = WiFi.encryptionType(i);
#endif
}
doc.shrinkToFit();
this->bufferedWebServer->send(200, "application/json", doc);
this->bufferedWebServer->send(200, F("application/json"), doc);
WiFi.scanDelete();
});
// settings
this->webServer->on("/api/settings", HTTP_GET, [this]() {
this->webServer->on(F("/api/settings"), HTTP_GET, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
return this->webServer->send(401);
@@ -423,10 +423,10 @@ protected:
settingsToJson(settings, doc);
doc.shrinkToFit();
this->bufferedWebServer->send(200, "application/json", doc);
this->bufferedWebServer->send(200, F("application/json"), doc);
});
this->webServer->on("/api/settings", HTTP_POST, [this]() {
this->webServer->on(F("/api/settings"), HTTP_POST, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
return this->webServer->send(401);
@@ -461,7 +461,7 @@ protected:
settingsToJson(settings, doc);
doc.shrinkToFit();
this->bufferedWebServer->send(changed ? 201 : 200, "application/json", doc);
this->bufferedWebServer->send(changed ? 201 : 200, F("application/json"), doc);
if (changed) {
doc.clear();
@@ -474,7 +474,7 @@ protected:
// sensors list
this->webServer->on("/api/sensors", HTTP_GET, [this]() {
this->webServer->on(F("/api/sensors"), HTTP_GET, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
return this->webServer->send(401);
@@ -482,16 +482,16 @@ protected:
}
bool detailed = false;
if (this->webServer->hasArg("detailed")) {
detailed = this->webServer->arg("detailed").toInt() > 0;
if (this->webServer->hasArg(F("detailed"))) {
detailed = this->webServer->arg(F("detailed")).toInt() > 0;
}
JsonDocument doc;
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
if (detailed) {
auto& sSensor = Sensors::settings[sensorId];
doc[sensorId]["name"] = sSensor.name;
doc[sensorId]["purpose"] = static_cast<uint8_t>(sSensor.purpose);
doc[sensorId][FPSTR(S_NAME)] = sSensor.name;
doc[sensorId][FPSTR(S_PURPOSE)] = static_cast<uint8_t>(sSensor.purpose);
sensorResultToJson(sensorId, doc[sensorId]);
} else {
@@ -500,22 +500,22 @@ protected:
}
doc.shrinkToFit();
this->bufferedWebServer->send(200, "application/json", doc);
this->bufferedWebServer->send(200, F("application/json"), doc);
});
// sensor settings
this->webServer->on("/api/sensor", HTTP_GET, [this]() {
this->webServer->on(F("/api/sensor"), HTTP_GET, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
return this->webServer->send(401);
}
}
if (!this->webServer->hasArg("id")) {
if (!this->webServer->hasArg(F("id"))) {
return this->webServer->send(400);
}
auto id = this->webServer->arg("id");
auto id = this->webServer->arg(F("id"));
if (!isDigit(id.c_str())) {
return this->webServer->send(400);
}
@@ -529,10 +529,10 @@ protected:
JsonDocument doc;
sensorSettingsToJson(sensorId, Sensors::settings[sensorId], doc);
doc.shrinkToFit();
this->bufferedWebServer->send(200, "application/json", doc);
this->bufferedWebServer->send(200, F("application/json"), doc);
});
this->webServer->on("/api/sensor", HTTP_POST, [this]() {
this->webServer->on(F("/api/sensor"), HTTP_POST, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
return this->webServer->send(401);
@@ -540,16 +540,16 @@ protected:
}
#ifdef ARDUINO_ARCH_ESP8266
if (!this->webServer->hasArg("id") || this->webServer->args() != 1) {
if (!this->webServer->hasArg(F("id")) || this->webServer->args() != 1) {
return this->webServer->send(400);
}
#else
if (!this->webServer->hasArg("id") || this->webServer->args() != 2) {
if (!this->webServer->hasArg(F("id")) || this->webServer->args() != 2) {
return this->webServer->send(400);
}
#endif
auto id = this->webServer->arg("id");
auto id = this->webServer->arg(F("id"));
if (!isDigit(id.c_str())) {
return this->webServer->send(400);
}
@@ -592,7 +592,7 @@ protected:
sensorSettingsToJson(sensorId, sSettings, doc);
doc.shrinkToFit();
this->bufferedWebServer->send(changed ? 201 : 200, "application/json", doc);
this->bufferedWebServer->send(changed ? 201 : 200, F("application/json"), doc);
}
if (changed) {
@@ -603,15 +603,15 @@ protected:
// vars
this->webServer->on("/api/vars", HTTP_GET, [this]() {
this->webServer->on(F("/api/vars"), HTTP_GET, [this]() {
JsonDocument doc;
varsToJson(vars, doc);
doc.shrinkToFit();
this->bufferedWebServer->send(200, "application/json", doc);
this->bufferedWebServer->send(200, F("application/json"), doc);
});
this->webServer->on("/api/vars", HTTP_POST, [this]() {
this->webServer->on(F("/api/vars"), HTTP_POST, [this]() {
if (this->isAuthRequired()) {
if (!this->webServer->authenticate(settings.portal.login, settings.portal.password)) {
return this->webServer->send(401);
@@ -646,7 +646,7 @@ protected:
varsToJson(vars, doc);
doc.shrinkToFit();
this->bufferedWebServer->send(changed ? 201 : 200, "application/json", doc);
this->bufferedWebServer->send(changed ? 201 : 200, F("application/json"), doc);
if (changed) {
doc.clear();
@@ -656,78 +656,138 @@ protected:
}
});
this->webServer->on("/api/info", HTTP_GET, [this]() {
this->webServer->on(F("/api/info"), HTTP_GET, [this]() {
bool isConnected = network->isConnected();
JsonDocument doc;
doc["system"]["resetReason"] = getResetReason();
doc["system"]["uptime"] = millis() / 1000ul;
doc["network"]["hostname"] = networkSettings.hostname;
doc["network"]["mac"] = network->getStaMac();
doc["network"]["connected"] = isConnected;
doc["network"]["ssid"] = network->getStaSsid();
doc["network"]["signalQuality"] = isConnected ? NetworkMgr::rssiToSignalQuality(network->getRssi()) : 0;
doc["network"]["channel"] = isConnected ? network->getStaChannel() : 0;
doc["network"]["ip"] = isConnected ? network->getStaIp().toString() : "";
doc["network"]["subnet"] = isConnected ? network->getStaSubnet().toString() : "";
doc["network"]["gateway"] = isConnected ? network->getStaGateway().toString() : "";
doc["network"]["dns"] = isConnected ? network->getStaDns().toString() : "";
auto docSystem = doc[FPSTR(S_SYSTEM)].to<JsonObject>();
docSystem[FPSTR(S_RESET_REASON)] = getResetReason();
docSystem[FPSTR(S_UPTIME)] = millis() / 1000;
doc["build"]["version"] = BUILD_VERSION;
doc["build"]["date"] = __DATE__ " " __TIME__;
doc["build"]["env"] = BUILD_ENV;
auto docNetwork = doc[FPSTR(S_NETWORK)].to<JsonObject>();
docNetwork[FPSTR(S_HOSTNAME)] = networkSettings.hostname;
docNetwork[FPSTR(S_MAC)] = network->getStaMac();
docNetwork[FPSTR(S_CONNECTED)] = isConnected;
docNetwork[FPSTR(S_SSID)] = network->getStaSsid();
docNetwork[FPSTR(S_SIGNAL_QUALITY)] = isConnected ? NetworkMgr::rssiToSignalQuality(network->getRssi()) : 0;
docNetwork[FPSTR(S_CHANNEL)] = isConnected ? network->getStaChannel() : 0;
docNetwork[FPSTR(S_IP)] = isConnected ? network->getStaIp().toString() : "";
docNetwork[FPSTR(S_SUBNET)] = isConnected ? network->getStaSubnet().toString() : "";
docNetwork[FPSTR(S_GATEWAY)] = isConnected ? network->getStaGateway().toString() : "";
docNetwork[FPSTR(S_DNS)] = isConnected ? network->getStaDns().toString() : "";
doc["heap"]["total"] = getTotalHeap();
doc["heap"]["free"] = getFreeHeap();
doc["heap"]["minFree"] = getFreeHeap(true);
doc["heap"]["maxFreeBlock"] = getMaxFreeBlockHeap();
doc["heap"]["minMaxFreeBlock"] = getMaxFreeBlockHeap(true);
auto docBuild = doc[FPSTR(S_BUILD)].to<JsonObject>();
docBuild[FPSTR(S_VERSION)] = BUILD_VERSION;
docBuild[FPSTR(S_DATE)] = __DATE__ " " __TIME__;
docBuild[FPSTR(S_ENV)] = BUILD_ENV;
#ifdef ARDUINO_ARCH_ESP8266
doc["build"]["core"] = ESP.getCoreVersion();
doc["build"]["sdk"] = ESP.getSdkVersion();
doc["chip"]["model"] = esp_is_8285() ? "ESP8285" : "ESP8266";
doc["chip"]["rev"] = 0;
doc["chip"]["cores"] = 1;
doc["chip"]["freq"] = ESP.getCpuFreqMHz();
doc["flash"]["size"] = ESP.getFlashChipSize();
doc["flash"]["realSize"] = ESP.getFlashChipRealSize();
docBuild[FPSTR(S_CORE)] = ESP.getCoreVersion();
docBuild[FPSTR(S_SDK)] = ESP.getSdkVersion();
#elif ARDUINO_ARCH_ESP32
doc["build"]["core"] = ESP.getCoreVersion();
doc["build"]["sdk"] = ESP.getSdkVersion();
doc["chip"]["model"] = ESP.getChipModel();
doc["chip"]["rev"] = ESP.getChipRevision();
doc["chip"]["cores"] = ESP.getChipCores();
doc["chip"]["freq"] = ESP.getCpuFreqMHz();
doc["flash"]["size"] = ESP.getFlashChipSize();
doc["flash"]["realSize"] = doc["flash"]["size"];
docBuild[FPSTR(S_CORE)] = ESP.getCoreVersion();
docBuild[FPSTR(S_SDK)] = ESP.getSdkVersion();
#else
doc["build"]["core"] = 0;
doc["build"]["sdk"] = 0;
doc["chip"]["model"] = 0;
doc["chip"]["rev"] = 0;
doc["chip"]["cores"] = 0;
doc["chip"]["freq"] = 0;
doc["flash"]["size"] = 0;
doc["flash"]["realSize"] = 0;
docBuild[FPSTR(S_CORE)] = 0;
docBuild[FPSTR(S_SDK)] = 0;
#endif
auto docHeap = doc[FPSTR(S_HEAP)].to<JsonObject>();
docHeap[FPSTR(S_TOTAL)] = getTotalHeap();
docHeap[FPSTR(S_FREE)] = getFreeHeap();
docHeap[FPSTR(S_MIN_FREE)] = getFreeHeap(true);
docHeap[FPSTR(S_MAX_FREE_BLOCK)] = getMaxFreeBlockHeap();
docHeap[FPSTR(S_MIN_MAX_FREE_BLOCK)] = getMaxFreeBlockHeap(true);
auto docChip = doc[FPSTR(S_CHIP)].to<JsonObject>();
#ifdef ARDUINO_ARCH_ESP8266
docChip[FPSTR(S_MODEL)] = esp_is_8285() ? F("ESP8285") : F("ESP8266");
docChip[FPSTR(S_REV)] = 0;
docChip[FPSTR(S_CORES)] = 1;
docChip[FPSTR(S_FREQ)] = ESP.getCpuFreqMHz();
#elif ARDUINO_ARCH_ESP32
docChip[FPSTR(S_MODEL)] = ESP.getChipModel();
docChip[FPSTR(S_REV)] = ESP.getChipRevision();
docChip[FPSTR(S_CORES)] = ESP.getChipCores();
docChip[FPSTR(S_FREQ)] = ESP.getCpuFreqMHz();
#else
docChip[FPSTR(S_MODEL)] = 0;
docChip[FPSTR(S_REV)] = 0;
docChip[FPSTR(S_CORES)] = 0;
docChip[FPSTR(S_FREQ)] = 0;
#endif
auto docFlash = doc[FPSTR(S_FLASH)].to<JsonObject>();
#ifdef ARDUINO_ARCH_ESP8266
docFlash[FPSTR(S_SIZE)] = ESP.getFlashChipSize();
docFlash[FPSTR(S_REAL_SIZE)] = ESP.getFlashChipRealSize();
#elif ARDUINO_ARCH_ESP32
docFlash[FPSTR(S_SIZE)] = ESP.getFlashChipSize();
docFlash[FPSTR(S_REAL_SIZE)] = docFlash[FPSTR(S_SIZE)];
#else
docFlash[FPSTR(S_SIZE)] = 0;
docFlash[FPSTR(S_REAL_SIZE)] = 0;
#endif
doc.shrinkToFit();
this->bufferedWebServer->send(200, "application/json", doc);
this->bufferedWebServer->send(200, F("application/json"), doc);
});
this->webServer->on("/api/debug", HTTP_GET, [this]() {
this->webServer->on(F("/api/debug"), HTTP_GET, [this]() {
JsonDocument doc;
doc["build"]["version"] = BUILD_VERSION;
doc["build"]["date"] = __DATE__ " " __TIME__;
doc["build"]["env"] = BUILD_ENV;
doc["heap"]["total"] = getTotalHeap();
doc["heap"]["free"] = getFreeHeap();
doc["heap"]["minFree"] = getFreeHeap(true);
doc["heap"]["maxFreeBlock"] = getMaxFreeBlockHeap();
doc["heap"]["minMaxFreeBlock"] = getMaxFreeBlockHeap(true);
auto docBuild = doc[FPSTR(S_BUILD)].to<JsonObject>();
docBuild[FPSTR(S_VERSION)] = BUILD_VERSION;
docBuild[FPSTR(S_DATE)] = __DATE__ " " __TIME__;
docBuild[FPSTR(S_ENV)] = BUILD_ENV;
#ifdef ARDUINO_ARCH_ESP8266
docBuild[FPSTR(S_CORE)] = ESP.getCoreVersion();
docBuild[FPSTR(S_SDK)] = ESP.getSdkVersion();
#elif ARDUINO_ARCH_ESP32
docBuild[FPSTR(S_CORE)] = ESP.getCoreVersion();
docBuild[FPSTR(S_SDK)] = ESP.getSdkVersion();
#else
docBuild[FPSTR(S_CORE)] = 0;
docBuild[FPSTR(S_SDK)] = 0;
#endif
auto docHeap = doc[FPSTR(S_HEAP)].to<JsonObject>();
docHeap[FPSTR(S_TOTAL)] = getTotalHeap();
docHeap[FPSTR(S_FREE)] = getFreeHeap();
docHeap[FPSTR(S_MIN_FREE)] = getFreeHeap(true);
docHeap[FPSTR(S_MAX_FREE_BLOCK)] = getMaxFreeBlockHeap();
docHeap[FPSTR(S_MIN_MAX_FREE_BLOCK)] = getMaxFreeBlockHeap(true);
auto docChip = doc[FPSTR(S_CHIP)].to<JsonObject>();
#ifdef ARDUINO_ARCH_ESP8266
docChip[FPSTR(S_MODEL)] = esp_is_8285() ? F("ESP8285") : F("ESP8266");
docChip[FPSTR(S_REV)] = 0;
docChip[FPSTR(S_CORES)] = 1;
docChip[FPSTR(S_FREQ)] = ESP.getCpuFreqMHz();
#elif ARDUINO_ARCH_ESP32
docChip[FPSTR(S_MODEL)] = ESP.getChipModel();
docChip[FPSTR(S_REV)] = ESP.getChipRevision();
docChip[FPSTR(S_CORES)] = ESP.getChipCores();
docChip[FPSTR(S_FREQ)] = ESP.getCpuFreqMHz();
#else
docChip[FPSTR(S_MODEL)] = 0;
docChip[FPSTR(S_REV)] = 0;
docChip[FPSTR(S_CORES)] = 0;
docChip[FPSTR(S_FREQ)] = 0;
#endif
auto docFlash = doc[FPSTR(S_FLASH)].to<JsonObject>();
#ifdef ARDUINO_ARCH_ESP8266
docFlash[FPSTR(S_SIZE)] = ESP.getFlashChipSize();
docFlash[FPSTR(S_REAL_SIZE)] = ESP.getFlashChipRealSize();
#elif ARDUINO_ARCH_ESP32
docFlash[FPSTR(S_SIZE)] = ESP.getFlashChipSize();
docFlash[FPSTR(S_REAL_SIZE)] = docFlash[FPSTR(S_SIZE)];
#else
docFlash[FPSTR(S_SIZE)] = 0;
docFlash[FPSTR(S_REAL_SIZE)] = 0;
#endif
#if defined(ARDUINO_ARCH_ESP32)
auto reason = esp_reset_reason();
@@ -738,58 +798,30 @@ protected:
#else
if (false) {
#endif
doc["crash"]["reason"] = getResetReason();
doc["crash"]["core"] = CrashRecorder::ext.core;
doc["crash"]["heap"] = CrashRecorder::ext.heap;
doc["crash"]["uptime"] = CrashRecorder::ext.uptime;
auto docCrash = doc[FPSTR(S_CRASH)].to<JsonObject>();
docCrash[FPSTR(S_REASON)] = getResetReason();
docCrash[FPSTR(S_CORE)] = CrashRecorder::ext.core;
docCrash[FPSTR(S_HEAP)] = CrashRecorder::ext.heap;
docCrash[FPSTR(S_UPTIME)] = CrashRecorder::ext.uptime;
if (CrashRecorder::backtrace.length > 0 && CrashRecorder::backtrace.length <= CrashRecorder::backtraceMaxLength) {
String backtraceStr;
arr2str(backtraceStr, CrashRecorder::backtrace.data, CrashRecorder::backtrace.length);
doc["crash"]["backtrace"]["data"] = backtraceStr;
doc["crash"]["backtrace"]["continues"] = CrashRecorder::backtrace.continues;
docCrash[FPSTR(S_BACKTRACE)][FPSTR(S_DATA)] = backtraceStr;
docCrash[FPSTR(S_BACKTRACE)][FPSTR(S_CONTINUES)] = CrashRecorder::backtrace.continues;
}
if (CrashRecorder::epc.length > 0 && CrashRecorder::epc.length <= CrashRecorder::epcMaxLength) {
String epcStr;
arr2str(epcStr, CrashRecorder::epc.data, CrashRecorder::epc.length);
doc["crash"]["epc"] = epcStr;
docCrash[FPSTR(S_EPC)] = epcStr;
}
}
#ifdef ARDUINO_ARCH_ESP8266
doc["build"]["core"] = ESP.getCoreVersion();
doc["build"]["sdk"] = ESP.getSdkVersion();
doc["chip"]["model"] = esp_is_8285() ? "ESP8285" : "ESP8266";
doc["chip"]["rev"] = 0;
doc["chip"]["cores"] = 1;
doc["chip"]["freq"] = ESP.getCpuFreqMHz();
doc["flash"]["size"] = ESP.getFlashChipSize();
doc["flash"]["realSize"] = ESP.getFlashChipRealSize();
#elif ARDUINO_ARCH_ESP32
doc["build"]["core"] = ESP.getCoreVersion();
doc["build"]["sdk"] = ESP.getSdkVersion();
doc["chip"]["model"] = ESP.getChipModel();
doc["chip"]["rev"] = ESP.getChipRevision();
doc["chip"]["cores"] = ESP.getChipCores();
doc["chip"]["freq"] = ESP.getCpuFreqMHz();
doc["flash"]["size"] = ESP.getFlashChipSize();
doc["flash"]["realSize"] = doc["flash"]["size"];
#else
doc["build"]["core"] = 0;
doc["build"]["sdk"] = 0;
doc["chip"]["model"] = 0;
doc["chip"]["rev"] = 0;
doc["chip"]["cores"] = 0;
doc["chip"]["freq"] = 0;
doc["flash"]["size"] = 0;
doc["flash"]["realSize"] = 0;
#endif
doc.shrinkToFit();
this->webServer->sendHeader(F("Content-Disposition"), F("attachment; filename=\"debug.json\""));
this->bufferedWebServer->send(200, "application/json", doc, true);
this->bufferedWebServer->send(200, F("application/json"), doc, true);
});
@@ -798,14 +830,14 @@ protected:
Log.straceln(FPSTR(L_PORTAL_WEBSERVER), F("Page not found, uri: %s"), this->webServer->uri().c_str());
const String uri = this->webServer->uri();
if (uri.equals("/")) {
this->webServer->send(200, "text/plain", F("The file system is not flashed!"));
if (uri.equals(F("/"))) {
this->webServer->send(200, F("text/plain"), F("The file system is not flashed!"));
} else if (network->isApEnabled()) {
this->onCaptivePortal();
} else {
this->webServer->send(404, "text/plain", F("Page not found"));
this->webServer->send(404, F("text/plain"), F("Page not found"));
}
});
@@ -877,26 +909,28 @@ protected:
void onCaptivePortal() {
const String uri = this->webServer->uri();
if (uri.equals("/connecttest.txt")) {
if (uri.equals(F("/connecttest.txt"))) {
this->webServer->sendHeader(F("Location"), F("http://logout.net"));
this->webServer->send(302);
Log.straceln(FPSTR(L_PORTAL_CAPTIVE), F("Redirect to http://logout.net with 302 code"));
} else if (uri.equals("/wpad.dat")) {
} else if (uri.equals(F("/wpad.dat"))) {
this->webServer->send(404);
Log.straceln(FPSTR(L_PORTAL_CAPTIVE), F("Send empty page with 404 code"));
} else if (uri.equals("/success.txt")) {
} else if (uri.equals(F("/success.txt"))) {
this->webServer->send(200);
Log.straceln(FPSTR(L_PORTAL_CAPTIVE), F("Send empty page with 200 code"));
} else {
String portalUrl = "http://" + network->getApIp().toString() + '/';
String portalUrl = F("http://");
portalUrl += network->getApIp().toString();
portalUrl += '/';
this->webServer->sendHeader("Location", portalUrl.c_str());
this->webServer->sendHeader(F("Location"), portalUrl.c_str());
this->webServer->send(302);
Log.straceln(FPSTR(L_PORTAL_CAPTIVE), F("Redirect to portal page with 302 code"));

View File

@@ -61,16 +61,26 @@ protected:
void loop() {
if (isPollingDallasSensors()) {
pollingDallasSensors(false);
this->yield();
}
if (millis() - this->globalLastPollingTime > this->globalPollingInterval) {
makeDallasInstances();
cleanDallasInstances();
makeDallasInstances();
this->yield();
searchDallasSensors();
fillingAddressesDallasSensors();
this->yield();
pollingDallasSensors();
this->yield();
pollingNtcSensors();
this->yield();
pollingBleSensors();
this->yield();
this->globalLastPollingTime = millis();
}

View File

@@ -236,7 +236,7 @@ struct Variables {
struct {
bool state = false;
unsigned long lastEnableTime = 0;
unsigned long lastEnabledTime = 0;
} externalPump;
struct {

View File

@@ -1,3 +1,6 @@
#define ARDUINOJSON_USE_DOUBLE 0
#define ARDUINOJSON_USE_LONG_LONG 0
#include <Arduino.h>
#include <ArduinoJson.h>
#include <FileData.h>

View File

@@ -3,32 +3,191 @@
#define PROGMEM
#endif
const char L_SETTINGS[] PROGMEM = "SETTINGS";
const char L_SETTINGS_OT[] PROGMEM = "SETTINGS.OT";
const char L_SETTINGS_DHW[] PROGMEM = "SETTINGS.DHW";
const char L_SETTINGS_HEATING[] PROGMEM = "SETTINGS.HEATING";
const char L_NETWORK[] PROGMEM = "NETWORK";
const char L_NETWORK_SETTINGS[] PROGMEM = "NETWORK.SETTINGS";
const char L_PORTAL_WEBSERVER[] PROGMEM = "PORTAL.WEBSERVER";
const char L_PORTAL_DNSSERVER[] PROGMEM = "PORTAL.DNSSERVER";
const char L_PORTAL_CAPTIVE[] PROGMEM = "PORTAL.CAPTIVE";
const char L_PORTAL_OTA[] PROGMEM = "PORTAL.OTA";
const char L_MAIN[] PROGMEM = "MAIN";
const char L_MQTT[] PROGMEM = "MQTT";
const char L_MQTT_HA[] PROGMEM = "MQTT.HA";
const char L_MQTT_MSG[] PROGMEM = "MQTT.MSG";
const char L_OT[] PROGMEM = "OT";
const char L_OT_DHW[] PROGMEM = "OT.DHW";
const char L_OT_HEATING[] PROGMEM = "OT.HEATING";
const char L_OT_CH2[] PROGMEM = "OT.CH2";
const char L_SENSORS[] PROGMEM = "SENSORS";
const char L_SENSORS_SETTINGS[] PROGMEM = "SENSORS.SETTINGS";
const char L_SENSORS_DALLAS[] PROGMEM = "SENSORS.DALLAS";
const char L_SENSORS_NTC[] PROGMEM = "SENSORS.NTC";
const char L_SENSORS_BLE[] PROGMEM = "SENSORS.BLE";
const char L_REGULATOR[] PROGMEM = "REGULATOR";
const char L_REGULATOR_PID[] PROGMEM = "REGULATOR.PID";
const char L_REGULATOR_EQUITHERM[] PROGMEM = "REGULATOR.EQUITHERM";
const char L_CASCADE_INPUT[] PROGMEM = "CASCADE.INPUT";
const char L_CASCADE_OUTPUT[] PROGMEM = "CASCADE.OUTPUT";
const char L_EXTPUMP[] PROGMEM = "EXTPUMP";
const char L_SETTINGS[] PROGMEM = "SETTINGS";
const char L_SETTINGS_OT[] PROGMEM = "SETTINGS.OT";
const char L_SETTINGS_DHW[] PROGMEM = "SETTINGS.DHW";
const char L_SETTINGS_HEATING[] PROGMEM = "SETTINGS.HEATING";
const char L_NETWORK[] PROGMEM = "NETWORK";
const char L_NETWORK_SETTINGS[] PROGMEM = "NETWORK.SETTINGS";
const char L_PORTAL_WEBSERVER[] PROGMEM = "PORTAL.WEBSERVER";
const char L_PORTAL_DNSSERVER[] PROGMEM = "PORTAL.DNSSERVER";
const char L_PORTAL_CAPTIVE[] PROGMEM = "PORTAL.CAPTIVE";
const char L_PORTAL_OTA[] PROGMEM = "PORTAL.OTA";
const char L_MAIN[] PROGMEM = "MAIN";
const char L_MQTT[] PROGMEM = "MQTT";
const char L_MQTT_HA[] PROGMEM = "MQTT.HA";
const char L_MQTT_MSG[] PROGMEM = "MQTT.MSG";
const char L_OT[] PROGMEM = "OT";
const char L_OT_DHW[] PROGMEM = "OT.DHW";
const char L_OT_HEATING[] PROGMEM = "OT.HEATING";
const char L_OT_CH2[] PROGMEM = "OT.CH2";
const char L_SENSORS[] PROGMEM = "SENSORS";
const char L_SENSORS_SETTINGS[] PROGMEM = "SENSORS.SETTINGS";
const char L_SENSORS_DALLAS[] PROGMEM = "SENSORS.DALLAS";
const char L_SENSORS_NTC[] PROGMEM = "SENSORS.NTC";
const char L_SENSORS_BLE[] PROGMEM = "SENSORS.BLE";
const char L_REGULATOR[] PROGMEM = "REGULATOR";
const char L_REGULATOR_PID[] PROGMEM = "REGULATOR.PID";
const char L_REGULATOR_EQUITHERM[] PROGMEM = "REGULATOR.EQUITHERM";
const char L_CASCADE_INPUT[] PROGMEM = "CASCADE.INPUT";
const char L_CASCADE_OUTPUT[] PROGMEM = "CASCADE.OUTPUT";
const char L_EXTPUMP[] PROGMEM = "EXTPUMP";
const char S_ACTIONS[] PROGMEM = "actions";
const char S_ACTIVE[] PROGMEM = "active";
const char S_ADDRESS[] PROGMEM = "address";
const char S_ANTI_STUCK_INTERVAL[] PROGMEM = "antiStuckInterval";
const char S_ANTI_STUCK_TIME[] PROGMEM = "antiStuckTime";
const char S_AP[] PROGMEM = "ap";
const char S_APP_VERSION[] PROGMEM = "appVersion";
const char S_AUTH[] PROGMEM = "auth";
const char S_BACKTRACE[] PROGMEM = "backtrace";
const char S_BATTERY[] PROGMEM = "battery";
const char S_BAUDRATE[] PROGMEM = "baudrate";
const char S_BLOCKING[] PROGMEM = "blocking";
const char S_BSSID[] PROGMEM = "bssid";
const char S_BUILD[] PROGMEM = "build";
const char S_CASCADE_CONTROL[] PROGMEM = "cascadeControl";
const char S_CHANNEL[] PROGMEM = "channel";
const char S_CHIP[] PROGMEM = "chip";
const char S_CODE[] PROGMEM = "code";
const char S_CONNECTED[] PROGMEM = "connected";
const char S_CONTINUES[] PROGMEM = "continues";
const char S_CORE[] PROGMEM = "core";
const char S_CORES[] PROGMEM = "cores";
const char S_CRASH[] PROGMEM = "crash";
const char S_CURRENT_TEMP[] PROGMEM = "currentTemp";
const char S_DATA[] PROGMEM = "data";
const char S_DATE[] PROGMEM = "date";
const char S_DHW[] PROGMEM = "dhw";
const char S_DHW_BLOCKING[] PROGMEM = "dhwBlocking";
const char S_DHW_PRESENT[] PROGMEM = "dhwPresent";
const char S_DHW_TO_CH2[] PROGMEM = "dhwToCh2";
const char S_DIAG[] PROGMEM = "diag";
const char S_DNS[] PROGMEM = "dns";
const char S_DT[] PROGMEM = "dt";
const char S_D_FACTOR[] PROGMEM = "d_factor";
const char S_EMERGENCY[] PROGMEM = "emergency";
const char S_ENABLED[] PROGMEM = "enabled";
const char S_ENV[] PROGMEM = "env";
const char S_EPC[] PROGMEM = "epc";
const char S_EQUITHERM[] PROGMEM = "equitherm";
const char S_EXTERNAL_PUMP[] PROGMEM = "externalPump";
const char S_FACTOR[] PROGMEM = "factor";
const char S_FAULT[] PROGMEM = "fault";
const char S_FILTERING[] PROGMEM = "filtering";
const char S_FILTERING_FACTOR[] PROGMEM = "filteringFactor";
const char S_FLAGS[] PROGMEM = "flags";
const char S_FLAME[] PROGMEM = "flame";
const char S_FLASH[] PROGMEM = "flash";
const char S_FREE[] PROGMEM = "free";
const char S_FREQ[] PROGMEM = "freq";
const char S_GATEWAY[] PROGMEM = "gateway";
const char S_GET_MIN_MAX_TEMP[] PROGMEM = "getMinMaxTemp";
const char S_GPIO[] PROGMEM = "gpio";
const char S_HEAP[] PROGMEM = "heap";
const char S_HEATING[] PROGMEM = "heating";
const char S_HEATING_CH1_TO_CH2[] PROGMEM = "heatingCh1ToCh2";
const char S_HEATING_CH2_ENABLED[] PROGMEM = "heatingCh2Enabled";
const char S_HIDDEN[] PROGMEM = "hidden";
const char S_HOME_ASSISTANT_DISCOVERY[] PROGMEM = "homeAssistantDiscovery";
const char S_HOSTNAME[] PROGMEM = "hostname";
const char S_HUMIDITY[] PROGMEM = "humidity";
const char S_HYSTERESIS[] PROGMEM = "hysteresis";
const char S_ID[] PROGMEM = "id";
const char S_IMMERGAS_FIX[] PROGMEM = "immergasFix";
const char S_INDOOR_TEMP[] PROGMEM = "indoorTemp";
const char S_INDOOR_TEMP_CONTROL[] PROGMEM = "indoorTempControl";
const char S_IN_GPIO[] PROGMEM = "inGpio";
const char S_INPUT[] PROGMEM = "input";
const char S_INTERVAL[] PROGMEM = "interval";
const char S_INVERT_STATE[] PROGMEM = "invertState";
const char S_IP[] PROGMEM = "ip";
const char S_I_FACTOR[] PROGMEM = "i_factor";
const char S_K_FACTOR[] PROGMEM = "k_factor";
const char S_LOGIN[] PROGMEM = "login";
const char S_LOG_LEVEL[] PROGMEM = "logLevel";
const char S_MAC[] PROGMEM = "mac";
const char S_MASTER[] PROGMEM = "master";
const char S_MAX[] PROGMEM = "max";
const char S_MAX_FREE_BLOCK[] PROGMEM = "maxFreeBlock";
const char S_MAX_MODULATION[] PROGMEM = "maxModulation";
const char S_MAX_POWER[] PROGMEM = "maxPower";
const char S_MAX_TEMP[] PROGMEM = "maxTemp";
const char S_MEMBER_ID[] PROGMEM = "memberId";
const char S_MIN[] PROGMEM = "min";
const char S_MIN_FREE[] PROGMEM = "minFree";
const char S_MIN_MAX_FREE_BLOCK[] PROGMEM = "minMaxFreeBlock";
const char S_MIN_POWER[] PROGMEM = "minPower";
const char S_MIN_TEMP[] PROGMEM = "minTemp";
const char S_MODEL[] PROGMEM = "model";
const char S_MODULATION[] PROGMEM = "modulation";
const char S_MODULATION_SYNC_WITH_HEATING[] PROGMEM = "modulationSyncWithHeating";
const char S_MQTT[] PROGMEM = "mqtt";
const char S_NAME[] PROGMEM = "name";
const char S_NATIVE_HEATING_CONTROL[] PROGMEM = "nativeHeatingControl";
const char S_NETWORK[] PROGMEM = "network";
const char S_N_FACTOR[] PROGMEM = "n_factor";
const char S_OFFSET[] PROGMEM = "offset";
const char S_ON_ENABLED_HEATING[] PROGMEM = "onEnabledHeating";
const char S_ON_FAULT[] PROGMEM = "onFault";
const char S_ON_LOSS_CONNECTION[] PROGMEM = "onLossConnection";
const char S_OPENTHERM[] PROGMEM = "opentherm";
const char S_OUTDOOR_TEMP[] PROGMEM = "outdoorTemp";
const char S_OUT_GPIO[] PROGMEM = "outGpio";
const char S_OUTPUT[] PROGMEM = "output";
const char S_PASSWORD[] PROGMEM = "password";
const char S_PID[] PROGMEM = "pid";
const char S_PORT[] PROGMEM = "port";
const char S_PORTAL[] PROGMEM = "portal";
const char S_POST_CIRCULATION_TIME[] PROGMEM = "postCirculationTime";
const char S_POWER[] PROGMEM = "power";
const char S_PREFIX[] PROGMEM = "prefix";
const char S_PROTOCOL_VERSION[] PROGMEM = "protocolVersion";
const char S_PURPOSE[] PROGMEM = "purpose";
const char S_P_FACTOR[] PROGMEM = "p_factor";
const char S_REAL_SIZE[] PROGMEM = "realSize";
const char S_REASON[] PROGMEM = "reason";
const char S_RESET_DIAGNOSTIC[] PROGMEM = "resetDiagnostic";
const char S_RESET_FAULT[] PROGMEM = "resetFault";
const char S_RESET_REASON[] PROGMEM = "resetReason";
const char S_RESTART[] PROGMEM = "restart";
const char S_RETURN_TEMP[] PROGMEM = "returnTemp";
const char S_REV[] PROGMEM = "rev";
const char S_RSSI[] PROGMEM = "rssi";
const char S_RX_LED_GPIO[] PROGMEM = "rxLedGpio";
const char S_SDK[] PROGMEM = "sdk";
const char S_SENSORS[] PROGMEM = "sensors";
const char S_SERIAL[] PROGMEM = "serial";
const char S_SERVER[] PROGMEM = "server";
const char S_SETTINGS[] PROGMEM = "settings";
const char S_SIGNAL_QUALITY[] PROGMEM = "signalQuality";
const char S_SIZE[] PROGMEM = "size";
const char S_SLAVE[] PROGMEM = "slave";
const char S_SSID[] PROGMEM = "ssid";
const char S_STA[] PROGMEM = "sta";
const char S_STATE[] PROGMEM = "state";
const char S_STATIC_CONFIG[] PROGMEM = "staticConfig";
const char S_STATUS_LED_GPIO[] PROGMEM = "statusLedGpio";
const char S_SUBNET[] PROGMEM = "subnet";
const char S_SUMMER_WINTER_MODE[] PROGMEM = "summerWinterMode";
const char S_SYSTEM[] PROGMEM = "system";
const char S_TARGET[] PROGMEM = "target";
const char S_TARGET_TEMP[] PROGMEM = "targetTemp";
const char S_TELNET[] PROGMEM = "telnet";
const char S_TEMPERATURE[] PROGMEM = "temperature";
const char S_THRESHOLD_TIME[] PROGMEM = "thresholdTime";
const char S_TOTAL[] PROGMEM = "total";
const char S_TRESHOLD_TIME[] PROGMEM = "tresholdTime";
const char S_TURBO[] PROGMEM = "turbo";
const char S_TURBO_FACTOR[] PROGMEM = "turboFactor";
const char S_TYPE[] PROGMEM = "type";
const char S_T_FACTOR[] PROGMEM = "t_factor";
const char S_UNIT_SYSTEM[] PROGMEM = "unitSystem";
const char S_UPTIME[] PROGMEM = "uptime";
const char S_USE[] PROGMEM = "use";
const char S_USE_DHCP[] PROGMEM = "useDhcp";
const char S_USER[] PROGMEM = "user";
const char S_VALUE[] PROGMEM = "value";
const char S_VERSION[] PROGMEM = "version";

File diff suppressed because it is too large Load Diff