refactor: refactoring after #144

This commit is contained in:
Yurii
2025-03-02 22:44:53 +03:00
parent e5f4281d4c
commit 3e61dabeab
14 changed files with 430 additions and 330 deletions

View File

@@ -840,19 +840,19 @@ public:
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_SWITCH), F("equitherm")).c_str(), doc);
}
bool publishInputEquithermFactorN(bool enabledByDefault = true) {
bool publishInputEquithermSlope(bool enabledByDefault = true) {
JsonDocument doc;
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_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm_slope"));
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_NAME)] = F("Equitherm slope");
doc[FPSTR(HA_ICON)] = F("mdi:slope-uphill");
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_VALUE_TEMPLATE)] = F("{{ value_json.equitherm.slope|float(0)|round(3) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"equitherm\": {\"n_factor\" : {{ value }}}}");
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"equitherm\": {\"slope\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0.001f;
doc[FPSTR(HA_MAX)] = 10;
doc[FPSTR(HA_STEP)] = 0.001f;
@@ -860,79 +860,80 @@ public:
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_NUMBER), F("equitherm_n_factor")).c_str(), doc);
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_NUMBER), F("equitherm_slope")).c_str(), doc);
}
bool publishInputEquithermFactorK(bool enabledByDefault = true) {
bool publishInputEquithermExponent(bool enabledByDefault = true) {
JsonDocument doc;
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_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm_exponent"));
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_NAME)] = F("Equitherm exponent");
doc[FPSTR(HA_ICON)] = F("mdi:exponent");
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_VALUE_TEMPLATE)] = F("{{ value_json.equitherm.exponent|float(0)|round(3) }}");
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)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_NUMBER), F("equitherm_k_factor")).c_str(), doc);
}
bool publishInputEquithermFactorE(bool enabledByDefault = true) {
JsonDocument doc;
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_e"));
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 Exponent E");
doc[FPSTR(HA_ICON)] = F("mdi:alpha-e-circle-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.equitherm.e_factor|float(0)|round(2) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"equitherm\": {\"e_factor\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 1;
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"equitherm\": {\"exponent\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0.1;
doc[FPSTR(HA_MAX)] = 2;
doc[FPSTR(HA_STEP)] = 0.001f;
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_NUMBER), F("equitherm_exponent")).c_str(), doc);
}
bool publishInputEquithermShift(bool enabledByDefault = true) {
JsonDocument doc;
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_shift"));
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)] = FPSTR(S_TEMPERATURE);
doc[FPSTR(HA_NAME)] = F("Equitherm shift");
doc[FPSTR(HA_ICON)] = F("mdi:chart-areaspline");
doc[FPSTR(HA_STATE_TOPIC)] = this->settingsTopic.c_str();
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.equitherm.shift|float(0)|round(2) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"equitherm\": {\"shift\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = -15;
doc[FPSTR(HA_MAX)] = 15;
doc[FPSTR(HA_STEP)] = 0.01f;
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_NUMBER), F("equitherm_e_factor")).c_str(), doc);
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_NUMBER), F("equitherm_shift")).c_str(), doc);
}
bool publishInputEquithermFactorT(bool enabledByDefault = true) {
bool publishInputEquithermTargetDiffFactor(bool enabledByDefault = true) {
JsonDocument doc;
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_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm_target_diff_factor"));
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_NAME)] = F("Equitherm target diff factor");
doc[FPSTR(HA_ICON)] = F("mdi:chart-timeline-variant-shimmer");
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_VALUE_TEMPLATE)] = F("{{ value_json.equitherm.targetDiffFactor|float(0)|round(3) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setSettingsTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"equitherm\": {\"t_factor\" : {{ value }}}}");
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"equitherm\": {\"targetDiffFactor\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0;
doc[FPSTR(HA_MAX)] = 10;
doc[FPSTR(HA_STEP)] = 0.01f;
doc[FPSTR(HA_STEP)] = 0.001f;
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_NUMBER), F("equitherm_t_factor")).c_str(), doc);
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_NUMBER), F("equitherm_target_diff_factor")).c_str(), doc);
}

View File

@@ -502,9 +502,10 @@ protected:
// equitherm
this->haHelper->publishSwitchEquitherm();
this->haHelper->publishInputEquithermFactorN(false);
this->haHelper->publishInputEquithermFactorK(false);
this->haHelper->publishInputEquithermFactorT(false);
this->haHelper->publishInputEquithermSlope(false);
this->haHelper->publishInputEquithermExponent(false);
this->haHelper->publishInputEquithermShift(false);
this->haHelper->publishInputEquithermTargetDiffFactor(false);
// states
this->haHelper->publishStatusState();

View File

@@ -1,7 +1,5 @@
#include <Equitherm.h>
#include <GyverPID.h>
Equitherm etRegulator;
GyverPID pidRegulator(0, 0, 0);
@@ -146,40 +144,32 @@ protected:
// if use equitherm
if (settings.equitherm.enabled) {
unsigned short minTemp = settings.heating.minTemp;
unsigned short maxTemp = settings.heating.maxTemp;
float targetTemp = settings.heating.target;
float indoorTemp = vars.master.heating.indoorTemp;
float outdoorTemp = vars.master.heating.outdoorTemp;
float tempDelta = settings.heating.target - vars.master.heating.outdoorTemp;
float maxPoint = settings.heating.target - (
settings.heating.maxTemp - settings.heating.target
) / settings.equitherm.slope;
if (settings.system.unitSystem == UnitSystem::IMPERIAL) {
minTemp = f2c(minTemp);
maxTemp = f2c(maxTemp);
targetTemp = f2c(targetTemp);
indoorTemp = f2c(indoorTemp);
outdoorTemp = f2c(outdoorTemp);
float sf = (settings.heating.maxTemp - settings.heating.target) / pow(
settings.heating.target - maxPoint,
1.0f / settings.equitherm.exponent
);
float etResult = settings.heating.target + settings.equitherm.shift + sf * (
tempDelta >= 0
? pow(tempDelta, 1.0f / settings.equitherm.exponent)
: -(pow(-(tempDelta), 1.0f / settings.equitherm.exponent))
);
// add diff
if (this->indoorSensorsConnected && !settings.pid.enabled && !settings.heating.turbo) {
etResult += constrain(
settings.heating.target - vars.master.heating.indoorTemp,
-3.0f,
3.0f
) * settings.equitherm.targetDiffFactor;
}
if (!this->indoorSensorsConnected || settings.pid.enabled) {
etRegulator.Kt = 0.0f;
etRegulator.indoorTemp = 0.0f;
} else {
etRegulator.Kt = settings.heating.turbo ? 0.0f : settings.equitherm.t_factor;
etRegulator.indoorTemp = indoorTemp;
}
etRegulator.setLimits(minTemp, maxTemp);
etRegulator.Kn = settings.equitherm.n_factor;
etRegulator.Kk = settings.equitherm.k_factor;
etRegulator.Ke = settings.equitherm.e_factor;
etRegulator.targetTemp = targetTemp;
etRegulator.outdoorTemp = outdoorTemp;
float etResult = etRegulator.getResult();
if (settings.system.unitSystem == UnitSystem::IMPERIAL) {
etResult = c2f(etResult);
}
// limit
etResult = constrain(etResult, settings.heating.minTemp, settings.heating.maxTemp);
if (fabsf(prevEtResult - etResult) > 0.09f) {
prevEtResult = etResult;

View File

@@ -134,10 +134,10 @@ struct Settings {
struct {
bool enabled = false;
float n_factor = 0.7f;
float k_factor = 3.0f;
float t_factor = 2.0f;
float e_factor = 1.3f;
float slope = 0.7f;
float exponent = 1.3f;
float shift = 0.0f;
float targetDiffFactor = 2.0f;
} equitherm;
struct {

View File

@@ -73,12 +73,12 @@ const char S_DNS[] PROGMEM = "dns";
const char S_DT[] PROGMEM = "dt";
const char S_D_FACTOR[] PROGMEM = "d_factor";
const char S_D_MULTIPLIER[] PROGMEM = "d_multiplier";
const char S_E_FACTOR[] PROGMEM = "e_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_EXPONENT[] PROGMEM = "exponent";
const char S_EXTERNAL_PUMP[] PROGMEM = "externalPump";
const char S_FACTOR[] PROGMEM = "factor";
const char S_FAULT[] PROGMEM = "fault";
@@ -112,7 +112,6 @@ const char S_INVERT_STATE[] PROGMEM = "invertState";
const char S_IP[] PROGMEM = "ip";
const char S_I_FACTOR[] PROGMEM = "i_factor";
const char S_I_MULTIPLIER[] PROGMEM = "i_multiplier";
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";
@@ -138,7 +137,6 @@ const char S_NAME[] PROGMEM = "name";
const char S_NATIVE_HEATING_CONTROL[] PROGMEM = "nativeHeatingControl";
const char S_NETWORK[] PROGMEM = "network";
const char S_NTP[] PROGMEM = "ntp";
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";
@@ -174,9 +172,11 @@ 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_SHIFT[] PROGMEM = "shift";
const char S_SIGNAL_QUALITY[] PROGMEM = "signalQuality";
const char S_SIZE[] PROGMEM = "size";
const char S_SLAVE[] PROGMEM = "slave";
const char S_SLOPE[] PROGMEM = "slope";
const char S_SSID[] PROGMEM = "ssid";
const char S_STA[] PROGMEM = "sta";
const char S_STATE[] PROGMEM = "state";
@@ -187,6 +187,7 @@ 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_DIFF_FACTOR[] PROGMEM = "targetDiffFactor";
const char S_TARGET_TEMP[] PROGMEM = "targetTemp";
const char S_TELNET[] PROGMEM = "telnet";
const char S_TEMPERATURE[] PROGMEM = "temperature";
@@ -199,7 +200,6 @@ 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";

View File

@@ -500,10 +500,10 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
auto equitherm = dst[FPSTR(S_EQUITHERM)].to<JsonObject>();
equitherm[FPSTR(S_ENABLED)] = src.equitherm.enabled;
equitherm[FPSTR(S_N_FACTOR)] = roundf(src.equitherm.n_factor, 3);
equitherm[FPSTR(S_K_FACTOR)] = roundf(src.equitherm.k_factor, 3);
equitherm[FPSTR(S_E_FACTOR)] = roundf(src.equitherm.e_factor, 3);
equitherm[FPSTR(S_T_FACTOR)] = roundf(src.equitherm.t_factor, 3);
equitherm[FPSTR(S_SLOPE)] = roundf(src.equitherm.slope, 3);
equitherm[FPSTR(S_EXPONENT)] = roundf(src.equitherm.exponent, 3);
equitherm[FPSTR(S_SHIFT)] = roundf(src.equitherm.shift, 2);
equitherm[FPSTR(S_TARGET_DIFF_FACTOR)] = roundf(src.equitherm.targetDiffFactor, 3);
auto pid = dst[FPSTR(S_PID)].to<JsonObject>();
pid[FPSTR(S_ENABLED)] = src.pid.enabled;
@@ -1083,37 +1083,38 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
}
}
if (!src[FPSTR(S_EQUITHERM)][FPSTR(S_N_FACTOR)].isNull()) {
float value = src[FPSTR(S_EQUITHERM)][FPSTR(S_N_FACTOR)].as<float>();
if (!src[FPSTR(S_EQUITHERM)][FPSTR(S_SLOPE)].isNull()) {
float value = src[FPSTR(S_EQUITHERM)][FPSTR(S_SLOPE)].as<float>();
if (value > 0 && value <= 10 && fabsf(value - dst.equitherm.n_factor) > 0.0001f) {
dst.equitherm.n_factor = roundf(value, 3);
if (value > 0.0f && value <= 10.0f && fabsf(value - dst.equitherm.slope) > 0.0001f) {
dst.equitherm.slope = roundf(value, 3);
changed = true;
}
}
if (!src[FPSTR(S_EQUITHERM)][FPSTR(S_K_FACTOR)].isNull()) {
float value = src[FPSTR(S_EQUITHERM)][FPSTR(S_K_FACTOR)].as<float>();
if (!src[FPSTR(S_EQUITHERM)][FPSTR(S_EXPONENT)].isNull()) {
float value = src[FPSTR(S_EQUITHERM)][FPSTR(S_EXPONENT)].as<float>();
if (value >= 0 && value <= 10 && fabsf(value - dst.equitherm.k_factor) > 0.0001f) {
dst.equitherm.k_factor = roundf(value, 3);
if (value > 0.0f && value <= 2.0f && fabsf(value - dst.equitherm.exponent) > 0.0001f) {
dst.equitherm.exponent = roundf(value, 3);
changed = true;
}
}
if (!src[FPSTR(S_EQUITHERM)][FPSTR(S_E_FACTOR)].isNull()) {
float value = src[FPSTR(S_EQUITHERM)][FPSTR(S_E_FACTOR)].as<float>();
if (!src[FPSTR(S_EQUITHERM)][FPSTR(S_SHIFT)].isNull()) {
float value = src[FPSTR(S_EQUITHERM)][FPSTR(S_SHIFT)].as<float>();
if (value >= 1 && value <= 2 && fabsf(value - dst.equitherm.e_factor) > 0.0001f) {
dst.equitherm.e_factor = roundf(value, 3);
if (value >= -15.0f && value <= 15.0f && fabsf(value - dst.equitherm.shift) > 0.0001f) {
dst.equitherm.shift = roundf(value, 2);
changed = true;
}
}
if (!src[FPSTR(S_EQUITHERM)][FPSTR(S_T_FACTOR)].isNull()) {
float value = src[FPSTR(S_EQUITHERM)][FPSTR(S_T_FACTOR)].as<float>();
if (value >= 0 && value <= 10 && fabsf(value - dst.equitherm.t_factor) > 0.0001f) {
dst.equitherm.t_factor = roundf(value, 3);
if (!src[FPSTR(S_EQUITHERM)][FPSTR(S_TARGET_DIFF_FACTOR)].isNull()) {
float value = src[FPSTR(S_EQUITHERM)][FPSTR(S_TARGET_DIFF_FACTOR)].as<float>();
if (value >= 0.0f && value <= 10.0f && fabsf(value - dst.equitherm.targetDiffFactor) > 0.0001f) {
dst.equitherm.targetDiffFactor = roundf(value, 3);
changed = true;
}
}