diff --git a/AquaMQTT/include/Version.h b/AquaMQTT/include/Version.h index 1538231..7c24c3c 100644 --- a/AquaMQTT/include/Version.h +++ b/AquaMQTT/include/Version.h @@ -1,4 +1,4 @@ namespace aquamqtt { -constexpr char VERSION[] = "v1.4.0"; +constexpr char VERSION[] = "v1.4.1"; } \ No newline at end of file diff --git a/AquaMQTT/include/message/HMIMessage.h b/AquaMQTT/include/message/HMIMessage.h index 95a0085..ec5fba3 100644 --- a/AquaMQTT/include/message/HMIMessage.h +++ b/AquaMQTT/include/message/HMIMessage.h @@ -20,71 +20,79 @@ class HMIMessage void setWaterTempTarget(float targetTemperature); - HMIOperationMode operationMode(); + HMIOperationMode operationMode() const; - void setOperationMode(HMIOperationMode operationMode); + void setOperationMode(HMIOperationMode operationMode) const; - HMIOperationType getOperationType(); + HMIOperationType getOperationType() const; - void setOperationType(HMIOperationType operationType); + void setOperationType(HMIOperationType operationType) const; - bool isEmergencyModeEnabled(); + bool isEmergencyModeEnabled() const; - void setEmergencyMode(bool enabled); + void setEmergencyMode(bool enabled) const; - bool isHeatingElementEnabled(); + bool isHeatingElementEnabled() const; - void enableHeatingElement(bool enabled); + void enableHeatingElement(bool enabled) const; - bool isPVInputActivated(); + bool isPVInputActivated() const; - HMISetup setupMode(); + HMISetup setupMode() const; - uint8_t antiLegionellaModePerMonth(); + uint8_t antiLegionellaModePerMonth() const; void setAntiLegionellaModePerMonth(uint8_t value); - HMIAirDuctConfig airDuctConfig(); + HMIAirDuctConfig airDuctConfig() const; + + void setAirDuctConfig(HMIAirDuctConfig config) const; HMIInstallation installationMode(); + HMIFanExhaust fanExhaust() const; + + void setFanExhaustMode(HMIFanExhaust mode) const; + + bool exhaustFanChanged() const; + HMITestMode testMode(); void timerWindowStr(bool firstWindow, char* buffer); void setTimeWindowByStr(bool firstWindow, char* buffer, uint8_t length); - uint16_t timerWindowAStart(); + uint16_t timerWindowAStart() const; - uint16_t timerWindowALength(); + uint16_t timerWindowALength() const; - uint16_t timerWindowBStart(); + uint16_t timerWindowBStart() const; - uint16_t timerWindowBLength(); + uint16_t timerWindowBLength() const; - uint8_t timeHours(); + uint8_t timeHours() const; - void setTimeHours(uint8_t hour); + void setTimeHours(uint8_t hour) const; - uint8_t timeMinutes(); + uint8_t timeMinutes() const; - void setTimeMinutes(uint8_t minute); + void setTimeMinutes(uint8_t minute) const; - uint8_t timeSeconds(); + uint8_t timeSeconds() const; - void setTimeSeconds(uint8_t second); + void setTimeSeconds(uint8_t second) const; - uint16_t dateYear(); + uint16_t dateYear() const; - void setDateMonthAndYear(uint8_t month, uint16_t year); + void setDateMonthAndYear(uint8_t month, uint16_t year) const; - uint8_t dateMonth(); + uint8_t dateMonth() const; - uint8_t dateDay(); + uint8_t dateDay() const; - void setDateDay(uint8_t day); + void setDateDay(uint8_t day) const; - void setInstallationMode(HMIInstallation mode); + void setInstallationMode(HMIInstallation mode) const; bool waterTempTargetChanged() const; @@ -129,6 +137,7 @@ class HMIMessage bool mDateChanged; bool mTestModeChanged; bool mErrorRequestChanged; + bool mExhaustFanChanged; uint8_t* mData; }; diff --git a/AquaMQTT/include/message/MessageConstants.h b/AquaMQTT/include/message/MessageConstants.h index 9815c07..61bc217 100644 --- a/AquaMQTT/include/message/MessageConstants.h +++ b/AquaMQTT/include/message/MessageConstants.h @@ -131,6 +131,29 @@ static const char* testModeStr(HMITestMode config) } } +enum HMIFanExhaust +{ + EXHAUST_UNKNOWN = -1, + EXHAUST_STOP = 0, + EXHAUST_LOW_SPEED = 1, + EXHAUST_HIGH_SPEED = 2 +}; + +static const char* exhaustModeStr(HMIFanExhaust mode) +{ + switch (mode) + { + case EXHAUST_STOP: + return reinterpret_cast(mqtt::ENUM_CONFIG_EXHAUST_FAN_STOP); + case EXHAUST_LOW_SPEED: + return reinterpret_cast(mqtt::ENUM_CONFIG_EXHAUST_FAN_LOW_SPEED); + case EXHAUST_HIGH_SPEED: + return reinterpret_cast(mqtt::ENUM_CONFIG_EXHAUST_FAN_HIGH_SPEED); + default: + return reinterpret_cast(mqtt::ENUM_UNKNOWN); + } +} + enum HMIInstallation { INST_HP_UNKNOWN = -1, diff --git a/AquaMQTT/include/mqtt/IMQTTCallback.h b/AquaMQTT/include/mqtt/IMQTTCallback.h index 0358b0e..623fabb 100644 --- a/AquaMQTT/include/mqtt/IMQTTCallback.h +++ b/AquaMQTT/include/mqtt/IMQTTCallback.h @@ -10,6 +10,8 @@ namespace mqtt class IMQTTCallback { public: + virtual ~IMQTTCallback() = default; + // $prefix/aquamqtt/ctrl/operationMode + ENUM_OPERATION_MODE virtual void onOperationModeChanged(std::unique_ptr value) = 0; @@ -28,6 +30,12 @@ class IMQTTCallback // $prefix/aquamqtt/ctrl/configInstallation + ENUM INSTALLATION virtual void onInstallationModeChanged(std::unique_ptr mode) = 0; + // $prefix/aquamqtt/configFanExhaust + ENUM FAN EXHAUST + virtual void onFanExhaustModeChanged(std::unique_ptr mode) = 0; + + // $prefix/aquamqtt/configAirduct + virtual void onAirductConfigChanged(std::unique_ptr config) = 0; + // $prefic/aquamqtt/ctrl/flagPVModeHeatPump + bool virtual void onPVModeHeatpumpEnabled(bool enabled) = 0; diff --git a/AquaMQTT/include/mqtt/MQTTDefinitions.h b/AquaMQTT/include/mqtt/MQTTDefinitions.h index d8450dc..47e0d35 100644 --- a/AquaMQTT/include/mqtt/MQTTDefinitions.h +++ b/AquaMQTT/include/mqtt/MQTTDefinitions.h @@ -43,6 +43,10 @@ constexpr char ENUM_INSTALLATION_BOILER_BACKUP_EXT_OPT[] = { "BOILER BACKUP / B constexpr char ENUM_INSTALLATION_BOILER_BACKUP_EXT_PRIO[] = { "BOILER BACKUP / BOILER PRIORITY" }; constexpr char ENUM_INSTALLATION_SOLAR_BACKUP[] = { "HEAT PUMP AND SOLAR BACKUP" }; +constexpr char ENUM_CONFIG_EXHAUST_FAN_STOP[] = { "STOP" }; +constexpr char ENUM_CONFIG_EXHAUST_FAN_LOW_SPEED[] = { "LOW SPEED" }; +constexpr char ENUM_CONFIG_EXHAUST_FAN_HIGH_SPEED[] = { "HIGH SPEED" }; + constexpr char ENUM_TEST_MODE_OFF[] = { "OFF" }; constexpr char ENUM_TEST_MODE_IDLE[] = { "IDLE" }; constexpr char ENUM_TEST_MODE_ACTIVE_HEAT_PUMP[] = { "TESTING HEAT PUMP" }; @@ -108,6 +112,7 @@ constexpr char HMI_LEGIONELLA[] = { "antiLegionellaPerMonth" }; constexpr char HMI_TIMER_WINDOW_A[] = { "timerWindowA" }; constexpr char HMI_TIMER_WINDOW_B[] = { "timerWindowB" }; constexpr char HMI_AIR_DUCT_CONFIG[] = { "configAirduct" }; +constexpr char HMI_FAN_EXHAUST_CONFIG[] = { "configFanExhaust" }; constexpr char HMI_INSTALLATION_CONFIG[] = { "configInstallation" }; constexpr char HMI_TEST_MODE[] = { "testModeStatus" }; constexpr char HMI_SETUP_STATE[] = { "setupState" }; diff --git a/AquaMQTT/include/mqtt/MQTTDiscovery.h b/AquaMQTT/include/mqtt/MQTTDiscovery.h index 021effb..273640f 100644 --- a/AquaMQTT/include/mqtt/MQTTDiscovery.h +++ b/AquaMQTT/include/mqtt/MQTTDiscovery.h @@ -31,7 +31,7 @@ enum class MQTT_ITEM_SENSOR HMI_LEGIONELLA, HMI_TIMER_WINDOW_A, HMI_TIMER_WINDOW_B, - HMI_AIR_DUCT_CONFIG, + HMI_AIR_DUCT_CONFIG_DEPRECATED, HMI_TEST_MODE, HMI_SETUP_STATE, HMI_PV_INPUT_ACTIVATED, @@ -88,6 +88,8 @@ enum class MQTT_ITEM_BINARY_SENSOR MAIN_CAPABILITY_PV_INPUT, MAIN_CAPABILITY_EXT_COMM, MAIN_CAPABILITY_DRY_HEATING, + STATS_ACTIVE_OVERRIDE_HMI_FAN_EXHAUST_CONFIG, + STATS_ACTIVE_OVERRIDE_HMI_AIRDUCT_CONFIG, RESERVED_COUNT }; @@ -117,6 +119,8 @@ enum class MQTT_ITEM_SELECT HMI_OPERATION_MODE, HMI_OPERATION_TYPE, HMI_INSTALLATION_CONFIG, + HMI_FAN_EXHAUST_CONFIG, + HMI_AIR_DUCT_CONFIG, RESERVED_COUNT }; @@ -482,12 +486,8 @@ static bool buildConfiguration(uint8_t* buffer, uint16_t identifier, MQTT_ITEM_S doc["uniq_id"] = make_unique(temp, identifier, "hmi_setup"); doc["ic"] = "mdi:tablet-dashboard"; break; - case MQTT_ITEM_SENSOR::HMI_AIR_DUCT_CONFIG: - doc["name"] = "AirDuct Configuration"; - doc["stat_t"] = "~/hmi/configAirduct"; - doc["uniq_id"] = make_unique(temp, identifier, "hmi_airduct_cfg"); - doc["ic"] = "mdi:sign-direction"; - break; + case MQTT_ITEM_SENSOR::HMI_AIR_DUCT_CONFIG_DEPRECATED: + return false; case MQTT_ITEM_SENSOR::STATS_AQUAMQTT_MODE: doc["name"] = "AquaMQTT Mode"; doc["stat_t"] = "~/stats/aquamqttMode"; @@ -699,6 +699,26 @@ static bool buildConfiguration(uint8_t* buffer, uint16_t identifier, MQTT_ITEM_B doc["pl_off"] = "0"; doc["ent_cat"] = "diagnostic"; break; + case MQTT_ITEM_BINARY_SENSOR::STATS_ACTIVE_OVERRIDE_HMI_FAN_EXHAUST_CONFIG: + doc["name"] = "Active Override Configuration Fan Exhaust"; + doc["stat_t"] = "~/stats/activeOverrides"; + doc["val_tpl"] = "{{ value_json.configFanExhaust }}"; + doc["ic"] = "mdi:debug-step-over"; + doc["uniq_id"] = make_unique(temp, identifier, "main_state_override_fan_exh_cfg"); + doc["pl_on"] = "1"; + doc["pl_off"] = "0"; + doc["ent_cat"] = "diagnostic"; + break; + case MQTT_ITEM_BINARY_SENSOR::STATS_ACTIVE_OVERRIDE_HMI_AIRDUCT_CONFIG: + doc["name"] = "Active Override Configuration Air Duct"; + doc["stat_t"] = "~/stats/activeOverrides"; + doc["val_tpl"] = "{{ value_json.configAirduct }}"; + doc["ic"] = "mdi:debug-step-over"; + doc["uniq_id"] = make_unique(temp, identifier, "main_state_override_airduct_cfg"); + doc["pl_on"] = "1"; + doc["pl_off"] = "0"; + doc["ent_cat"] = "diagnostic"; + break; case MQTT_ITEM_BINARY_SENSOR::STATS_ACTIVE_OVERRIDE_HMI_TIME_DATE: doc["name"] = "Active Override Time/Date"; doc["stat_t"] = "~/stats/activeOverrides"; @@ -876,6 +896,28 @@ static bool buildConfiguration(uint8_t* buffer, uint16_t identifier, MQTT_ITEM_S doc["ops"][4] = mqtt::ENUM_INSTALLATION_THERMODYNAMICS_ONLY; doc["ops"][5] = mqtt::ENUM_INSTALLATION_SOLAR_BACKUP; break; + case MQTT_ITEM_SELECT::HMI_FAN_EXHAUST_CONFIG: + doc["name"] = "Fan Exhaust Configuration"; + doc["ent_cat"] = "config"; + doc["uniq_id"] = make_unique(temp, identifier, "hmi_fanExhaustConfig"); + doc["stat_t"] = "~/hmi/configFanExhaust"; + doc["cmd_t"] = "~/ctrl/configFanExhaust"; + doc["ic"] = "mdi:fan"; + doc["ops"][0] = mqtt::ENUM_CONFIG_EXHAUST_FAN_STOP; + doc["ops"][1] = mqtt::ENUM_CONFIG_EXHAUST_FAN_LOW_SPEED; + doc["ops"][2] = mqtt::ENUM_CONFIG_EXHAUST_FAN_HIGH_SPEED; + break; + case MQTT_ITEM_SELECT::HMI_AIR_DUCT_CONFIG: + doc["name"] = "AirDuct Configuration"; + doc["ent_cat"] = "config"; + doc["uniq_id"] = make_unique(temp, identifier, "hmi_airduct_cfg_sel"); + doc["stat_t"] = "~/hmi/configAirduct"; + doc["cmd_t"] = "~/ctrl/configAirduct"; + doc["ic"] = "mdi:sign-direction"; + doc["ops"][0] = mqtt::ENUM_AIR_DUCT_IN_IN; + doc["ops"][1] = mqtt::ENUM_AIR_DUCT_INT_EXT; + doc["ops"][2] = mqtt::ENUM_AIR_DUCT_EXT_EXT; + break; case MQTT_ITEM_SELECT::RESERVED_COUNT: default: return false; diff --git a/AquaMQTT/include/state/HMIStateProxy.h b/AquaMQTT/include/state/HMIStateProxy.h index e1b3fce..f95ef9c 100644 --- a/AquaMQTT/include/state/HMIStateProxy.h +++ b/AquaMQTT/include/state/HMIStateProxy.h @@ -16,6 +16,8 @@ struct AquaMqttOverrides bool heatingElementEnabled; bool emergencyModeEnabled; bool installationMode; + bool exhaustFanMode; + bool airductConfig; }; enum AquaMqttOverrideMode @@ -54,7 +56,7 @@ class HMIStateProxy : public mqtt::IMQTTCallback public: static HMIStateProxy& getInstance(); - virtual ~HMIStateProxy() = default; + ~HMIStateProxy() override = default; HMIStateProxy(const HMIStateProxy&) = delete; @@ -82,6 +84,10 @@ class HMIStateProxy : public mqtt::IMQTTCallback void onEmergencyModeEnabledChanged(std::unique_ptr enabled) override; + void onFanExhaustModeChanged(std::unique_ptr mode) override; + + void onAirductConfigChanged(std::unique_ptr config) override; + void onPVModeHeatpumpEnabled(bool enabled) override; bool isPVModeHeatPumpEnabled(); @@ -116,6 +122,8 @@ class HMIStateProxy : public mqtt::IMQTTCallback std::unique_ptr mOperationType; std::unique_ptr mOperationMode; std::unique_ptr mInstallationMode; + std::unique_ptr mFanExhaustMode; + std::unique_ptr mAirductConfig; std::unique_ptr mEmergencyModeEnabled; std::unique_ptr mHeatingElementEnabled; bool mPVModeHeatPump; diff --git a/AquaMQTT/include/state/MainStateProxy.h b/AquaMQTT/include/state/MainStateProxy.h index 935e2ec..a7a1ca7 100644 --- a/AquaMQTT/include/state/MainStateProxy.h +++ b/AquaMQTT/include/state/MainStateProxy.h @@ -56,6 +56,10 @@ class MainStateProxy : public mqtt::IMQTTCallback void onPVModeHeatElementEnabled(bool enabled) override; + void onFanExhaustModeChanged(std::unique_ptr mode) override; + + void onAirductConfigChanged(std::unique_ptr config) override; + void onResetOverrides() override; AquaMqttMainOverrides getOverrides(); diff --git a/AquaMQTT/src/message/HMIMessage.cpp b/AquaMQTT/src/message/HMIMessage.cpp index ca48bc3..b16e13b 100644 --- a/AquaMQTT/src/message/HMIMessage.cpp +++ b/AquaMQTT/src/message/HMIMessage.cpp @@ -21,6 +21,7 @@ HMIMessage::HMIMessage(uint8_t* data) , mDateChanged(false) , mTestModeChanged(false) , mErrorRequestChanged(false) + , mExhaustFanChanged(false) { } float HMIMessage::waterTempTarget() @@ -33,7 +34,7 @@ void HMIMessage::setWaterTempTarget(float targetTemperature) mData[1] = rawValue & 0xFF; mData[2] = (rawValue >> 8) & 0xFF; } -HMIOperationMode HMIMessage::operationMode() +HMIOperationMode HMIMessage::operationMode() const { switch (mData[3] & 0x0F) { @@ -51,14 +52,14 @@ HMIOperationMode HMIMessage::operationMode() return OM_UNKNOWN; } } -void HMIMessage::setOperationMode(HMIOperationMode operationMode) +void HMIMessage::setOperationMode(HMIOperationMode operationMode) const { if (operationMode != HMIOperationMode::OM_UNKNOWN) { mData[3] = (mData[3] & 0xF0) | (operationMode & 0x0F); } } -HMIOperationType HMIMessage::getOperationType() +HMIOperationType HMIMessage::getOperationType() const { if (mData[3] & 0x40) { @@ -67,7 +68,7 @@ HMIOperationType HMIMessage::getOperationType() return HMIOperationType::ALWAYS_ON; } -void HMIMessage::setOperationType(HMIOperationType operationType) +void HMIMessage::setOperationType(HMIOperationType operationType) const { if (operationType == HMIOperationType::TIMER) { @@ -78,86 +79,126 @@ void HMIMessage::setOperationType(HMIOperationType operationType) mData[3] = (mData[3] & ~(1 << 6)) | (false << 6); } } -bool HMIMessage::isEmergencyModeEnabled() +bool HMIMessage::isEmergencyModeEnabled() const { return mData[6] & 0x01; } -bool HMIMessage::isHeatingElementEnabled() +bool HMIMessage::isHeatingElementEnabled() const { return mData[9] & 0x04; } -bool HMIMessage::isPVInputActivated() +bool HMIMessage::isPVInputActivated() const { return mData[9] & 0x02; } -HMISetup HMIMessage::setupMode() +HMISetup HMIMessage::setupMode() const { if (mData[9] & 0x80) { return HMISetup::RESET; } - else if (mData[9] & 0x20) + if (mData[9] & 0x20) { return HMISetup::INCOMPLETE; } - else - { - return HMISetup::COMPLETED; - } + return HMISetup::COMPLETED; } -uint8_t HMIMessage::antiLegionellaModePerMonth() +uint8_t HMIMessage::antiLegionellaModePerMonth() const { return (uint8_t) (mData[5] & 0x0F); } -HMIAirDuctConfig HMIMessage::airDuctConfig() +HMIAirDuctConfig HMIMessage::airDuctConfig() const { switch ((uint8_t) (mData[5] & 0xF0)) { case 0: - return HMIAirDuctConfig::AD_INT_INT; + return AD_INT_INT; case 16: - return HMIAirDuctConfig::AD_INT_EXT; + return AD_INT_EXT; case 32: - return HMIAirDuctConfig::AD_EXT_EXT; + return AD_EXT_EXT; default: - return HMIAirDuctConfig::AD_UNKNOWN; + return AD_UNKNOWN; + } +} + +void HMIMessage::setAirDuctConfig(HMIAirDuctConfig config) const +{ + if (config == AD_UNKNOWN) + { + return; + } + + // clear bit 5 and 6 (INT/INT) + mData[5] &= 0b11001111; + + if (config == AD_INT_EXT) + { + mData[5] |= 0b00010000; + } + else if (config == AD_EXT_EXT) + { + mData[5] |= 0b00100000; } } HMIInstallation HMIMessage::installationMode() { if (mData[7] & 0x02) { - return HMIInstallation::INST_HP_AND_SOLAR; + return INST_HP_AND_SOLAR; } - else if (mData[7] & 0x01) + if (mData[7] & 0x01) { if (mData[7] & 0x10 && mData[7] & 0x20) { return HMIInstallation::INST_HP_AND_EXT_PRIO_EXT; } - else if (!(mData[7] & 0x10) && mData[7] & 0x20) + if (!(mData[7] & 0x10) && mData[7] & 0x20) { return HMIInstallation::INST_HP_AND_EXT_OPT_EXT; } - else if (mData[7] & 0x10 && !(mData[7] & 0x20)) + if (mData[7] & 0x10 && !(mData[7] & 0x20)) { return HMIInstallation::INST_HP_AND_EXT_OPT_HP; } - else - { - return HMIInstallation::INST_HP_AND_EXT_PRIO_HP; - } + return HMIInstallation::INST_HP_AND_EXT_PRIO_HP; } - else + return HMIInstallation::INST_HP_ONLY; +} + +HMIFanExhaust HMIMessage::fanExhaust() const +{ + switch ((uint8_t) (mData[8] & 0x03)) { - return HMIInstallation::INST_HP_ONLY; + case 0: + return EXHAUST_STOP; + case 1: + return EXHAUST_LOW_SPEED; + case 2: + return EXHAUST_HIGH_SPEED; + default: + return EXHAUST_UNKNOWN; } } +void HMIMessage::setFanExhaustMode(HMIFanExhaust mode) const +{ + if (mode == EXHAUST_UNKNOWN) + return; + + // clean the first two bits + mData[8] &= 0b11111100; + // apply value + mData[8] |= mode; +} +bool HMIMessage::exhaustFanChanged() const +{ + return mExhaustFanChanged; +} -void HMIMessage::setInstallationMode(HMIInstallation mode) +void HMIMessage::setInstallationMode(HMIInstallation mode) const { switch (mode) { @@ -207,23 +248,23 @@ HMITestMode HMIMessage::testMode() switch (mData[22]) { case 0: - return HMITestMode::TM_OFF; + return TM_OFF; case 1: - return HMITestMode::TM_ENTERED; + return TM_ENTERED; case 2: - return HMITestMode::TM_HEAT_PUMP; + return TM_HEAT_PUMP; case 3: - return HMITestMode::TM_HEAT_ELEMENT; + return TM_HEAT_ELEMENT; case 4: - return HMITestMode::TM_FAN_LOW; + return TM_FAN_LOW; case 5: - return HMITestMode::TM_FAN_HIGH; + return TM_FAN_HIGH; case 6: - return HMITestMode::TM_DEFROST; + return TM_DEFROST; case 8: - return HMITestMode::TM_HEAT_PUMP_AND_EXT; + return TM_HEAT_PUMP_AND_EXT; default: - return HMITestMode::TM_UNKNOWN; + return TM_UNKNOWN; } } void HMIMessage::timerWindowStr(bool firstWindow, char* buffer) @@ -240,71 +281,71 @@ void HMIMessage::timerWindowStr(bool firstWindow, char* buffer) const uint8_t endHours = (beginHours + lengthHours) % 24 + hourOverlap; sprintf(buffer, "%02d:%02d-%02d:%02d", beginHours, beginMinutes, endHours, endMinutes); } -uint16_t HMIMessage::timerWindowAStart() +uint16_t HMIMessage::timerWindowAStart() const { return mData[10]; } -uint16_t HMIMessage::timerWindowALength() +uint16_t HMIMessage::timerWindowALength() const { return mData[11]; } -uint16_t HMIMessage::timerWindowBStart() +uint16_t HMIMessage::timerWindowBStart() const { return mData[12]; } -uint16_t HMIMessage::timerWindowBLength() +uint16_t HMIMessage::timerWindowBLength() const { return mData[13]; } -uint8_t HMIMessage::timeHours() +uint8_t HMIMessage::timeHours() const { return mData[21]; } -void HMIMessage::setTimeHours(uint8_t hour) +void HMIMessage::setTimeHours(uint8_t hour) const { mData[21] = hour; } -uint8_t HMIMessage::timeMinutes() +uint8_t HMIMessage::timeMinutes() const { return mData[20]; } -void HMIMessage::setTimeMinutes(uint8_t minute) +void HMIMessage::setTimeMinutes(uint8_t minute) const { mData[20] = minute; } -uint8_t HMIMessage::timeSeconds() +uint8_t HMIMessage::timeSeconds() const { return mData[17]; } -void HMIMessage::setTimeSeconds(uint8_t second) +void HMIMessage::setTimeSeconds(uint8_t second) const { mData[17] = second; } -uint16_t HMIMessage::dateYear() +uint16_t HMIMessage::dateYear() const { return 2000 + (mData[19] / 2); } -void HMIMessage::setDateMonthAndYear(uint8_t month, uint16_t year) +void HMIMessage::setDateMonthAndYear(uint8_t month, uint16_t year) const { int pastJuly = month > 7 ? 1 : 0; mData[19] = ((year - 2000) * 2) + pastJuly; int monthValue = (pastJuly ? month - 8 : month) << 5; mData[18] = (mData[18] & 0x1F) | (monthValue & 0xE0); } -uint8_t HMIMessage::dateMonth() +uint8_t HMIMessage::dateMonth() const { return (mData[18] >> 5) + ((mData[19] % 2) * 8); } -uint8_t HMIMessage::dateDay() +uint8_t HMIMessage::dateDay() const { return mData[18] & 0x1F; } -void HMIMessage::setDateDay(uint8_t day) +void HMIMessage::setDateDay(uint8_t day) const { mData[18] = (mData[18] & 0xE0) | (day & 0x1F); } -void HMIMessage::setEmergencyMode(bool enabled) +void HMIMessage::setEmergencyMode(bool enabled) const { // Sanity: You cannot activate emergency mode if heating element is disabled if (enabled && isHeatingElementEnabled()) @@ -317,7 +358,7 @@ void HMIMessage::setEmergencyMode(bool enabled) } } -void HMIMessage::enableHeatingElement(bool enabled) +void HMIMessage::enableHeatingElement(bool enabled) const { if (enabled) { @@ -368,6 +409,7 @@ void HMIMessage::compareWith(uint8_t* data) mDateChanged = true; mTestModeChanged = true; mErrorRequestChanged = true; + mExhaustFanChanged = true; return; } @@ -394,6 +436,9 @@ void HMIMessage::compareWith(uint8_t* data) case 6: mEmergencyModeChanged = true; break; + case 8: + mExhaustFanChanged = true; + break; case 7: mInstallConfigChanged = true; break; diff --git a/AquaMQTT/src/state/HMIStateProxy.cpp b/AquaMQTT/src/state/HMIStateProxy.cpp index 273c739..0d1b4f2 100644 --- a/AquaMQTT/src/state/HMIStateProxy.cpp +++ b/AquaMQTT/src/state/HMIStateProxy.cpp @@ -24,6 +24,8 @@ HMIStateProxy::HMIStateProxy() , mEmergencyModeEnabled(nullptr) , mHeatingElementEnabled(nullptr) , mInstallationMode(nullptr) + , mFanExhaustMode(nullptr) + , mAirductConfig(nullptr) { } @@ -88,6 +90,16 @@ void HMIStateProxy::applyHMIOverrides(uint8_t* buffer) message.setInstallationMode(*mInstallationMode); } + if (mFanExhaustMode != nullptr) + { + message.setFanExhaustMode(*mFanExhaustMode); + } + + if (mAirductConfig != nullptr) + { + message.setAirDuctConfig(*mAirductConfig); + } + if (mOperationMode != nullptr) { message.setOperationMode(*mOperationMode); @@ -222,10 +234,43 @@ void HMIStateProxy::onEmergencyModeEnabledChanged(std::unique_ptr enabled) xSemaphoreGive(mMutex); } +void HMIStateProxy::onFanExhaustModeChanged(std::unique_ptr mode) +{ + if (!xSemaphoreTake(mMutex, portMAX_DELAY)) + { + return; + } -void HMIStateProxy::onPVModeHeatpumpEnabled(bool enabled) + mFanExhaustMode = std::move(mode); + + // message 194 has changed + if (mNotify != nullptr) + { + xTaskNotifyIndexed(mNotify, 0, (1UL << 8UL), eSetBits); + } + + xSemaphoreGive(mMutex); +} +void HMIStateProxy::onAirductConfigChanged(std::unique_ptr config) { + if (!xSemaphoreTake(mMutex, portMAX_DELAY)) + { + return; + } + + mAirductConfig = std::move(config); + + // message 194 has changed + if (mNotify != nullptr) + { + xTaskNotifyIndexed(mNotify, 0, (1UL << 8UL), eSetBits); + } + xSemaphoreGive(mMutex); +} + +void HMIStateProxy::onPVModeHeatpumpEnabled(bool enabled) +{ if (!xSemaphoreTake(mMutex, portMAX_DELAY)) { return; @@ -271,6 +316,8 @@ void HMIStateProxy::onResetOverrides() mTargetTemperature = std::unique_ptr(nullptr); mOperationType = std::unique_ptr(nullptr); mInstallationMode = std::unique_ptr(nullptr); + mFanExhaustMode = std::unique_ptr(nullptr); + mAirductConfig = std::unique_ptr(nullptr); mEmergencyModeEnabled = std::unique_ptr(nullptr); mHeatingElementEnabled = std::unique_ptr(nullptr); @@ -296,14 +343,15 @@ AquaMqttOverrides HMIStateProxy::getOverrides() case AM_MODE_STANDARD: retVal = AquaMqttOverrides{ mOperationMode != nullptr, mOperationType != nullptr, mTargetTemperature != nullptr, mHeatingElementEnabled != nullptr, - mEmergencyModeEnabled != nullptr, mInstallationMode != nullptr }; + mEmergencyModeEnabled != nullptr, mInstallationMode != nullptr, + mFanExhaustMode != nullptr, mAirductConfig != nullptr }; break; case AM_MODE_PV_HP_ONLY: case AM_MODE_PV_HE_ONLY: - retVal = AquaMqttOverrides{ true, true, true, true, true, true }; + retVal = AquaMqttOverrides{ true, true, true, true, true, true, false, false }; break; case AM_MODE_PV_FULL: - retVal = AquaMqttOverrides{ true, true, true, false, false, true }; + retVal = AquaMqttOverrides{ true, true, true, false, false, true, false, false }; break; } diff --git a/AquaMQTT/src/state/MainStateProxy.cpp b/AquaMQTT/src/state/MainStateProxy.cpp index 0f915c3..681a30a 100644 --- a/AquaMQTT/src/state/MainStateProxy.cpp +++ b/AquaMQTT/src/state/MainStateProxy.cpp @@ -128,6 +128,14 @@ void MainStateProxy::onPVModeHeatElementEnabled(bool enabled) xSemaphoreGive(mMutex); } +void MainStateProxy::onFanExhaustModeChanged(std::unique_ptr mode) +{ + // noop +} +void MainStateProxy::onAirductConfigChanged(std::unique_ptr config) +{ + // noop +} void MainStateProxy::onOperationTypeChanged(std::unique_ptr type) { diff --git a/AquaMQTT/src/task/MQTTTask.cpp b/AquaMQTT/src/task/MQTTTask.cpp index 20fd26b..f7b4826 100644 --- a/AquaMQTT/src/task/MQTTTask.cpp +++ b/AquaMQTT/src/task/MQTTTask.cpp @@ -56,32 +56,27 @@ void MQTTTask::messageReceived(String& topic, String& payload) { if (strstr_P(payload.c_str(), ENUM_OPERATION_MODE_ABSENCE) != nullptr) { - HMIStateProxy::getInstance().onOperationModeChanged( - std::unique_ptr(new HMIOperationMode(OM_ABSENCE))); + HMIStateProxy::getInstance().onOperationModeChanged(std::make_unique(OM_ABSENCE)); } else if (strstr_P(payload.c_str(), ENUM_OPERATION_MODE_BOOST) != nullptr) { - HMIStateProxy::getInstance().onOperationModeChanged( - std::unique_ptr(new HMIOperationMode(OM_BOOST))); + HMIStateProxy::getInstance().onOperationModeChanged(std::make_unique(OM_BOOST)); } else if (strstr_P(payload.c_str(), ENUM_OPERATION_MODE_AUTO) != nullptr) { - HMIStateProxy::getInstance().onOperationModeChanged( - std::unique_ptr(new HMIOperationMode(OM_AUTO))); + HMIStateProxy::getInstance().onOperationModeChanged(std::make_unique(OM_AUTO)); } else if (strstr_P(payload.c_str(), ENUM_OPERATION_MODE_ECO_ON) != nullptr) { - HMIStateProxy::getInstance().onOperationModeChanged( - std::unique_ptr(new HMIOperationMode(OM_ECO_ACTIVE))); + HMIStateProxy::getInstance().onOperationModeChanged(std::make_unique(OM_ECO_ACTIVE)); } else if (strstr_P(payload.c_str(), ENUM_OPERATION_MODE_ECO_OFF) != nullptr) { - HMIStateProxy::getInstance().onOperationModeChanged( - std::unique_ptr(new HMIOperationMode(OM_ECO_INACTIVE))); + HMIStateProxy::getInstance().onOperationModeChanged(std::make_unique(OM_ECO_INACTIVE)); } else { @@ -92,13 +87,11 @@ void MQTTTask::messageReceived(String& topic, String& payload) { if (strstr_P(payload.c_str(), ENUM_OPERATION_TYPE_TIMER) != nullptr) { - HMIStateProxy::getInstance().onOperationTypeChanged( - std::unique_ptr(new HMIOperationType(TIMER))); + HMIStateProxy::getInstance().onOperationTypeChanged(std::make_unique(TIMER)); } else if (strstr_P(payload.c_str(), ENUM_OPERATION_TYPE_ALWAYS_ON) != nullptr) { - HMIStateProxy::getInstance().onOperationTypeChanged( - std::unique_ptr(new HMIOperationType(ALWAYS_ON))); + HMIStateProxy::getInstance().onOperationTypeChanged(std::make_unique(ALWAYS_ON)); } else { @@ -115,7 +108,7 @@ void MQTTTask::messageReceived(String& topic, String& payload) else { bool result = (strcmp(payload.c_str(), "1") == 0); - HMIStateProxy::getInstance().onEmergencyModeEnabledChanged(std::unique_ptr(new bool(result))); + HMIStateProxy::getInstance().onEmergencyModeEnabledChanged(std::make_unique(result)); } } else if (strstr_P(topic.c_str(), HMI_HEATING_ELEMENT_ENABLED) != nullptr) @@ -127,7 +120,7 @@ void MQTTTask::messageReceived(String& topic, String& payload) else { bool result = (strcmp(payload.c_str(), "1") == 0); - HMIStateProxy::getInstance().onHeatingElementEnabledChanged(std::unique_ptr(new bool(result))); + HMIStateProxy::getInstance().onHeatingElementEnabledChanged(std::make_unique(result)); } } else if (strstr_P(topic.c_str(), HMI_HOT_WATER_TEMP_TARGET) != nullptr) @@ -138,51 +131,88 @@ void MQTTTask::messageReceived(String& topic, String& payload) } else { - HMIStateProxy::getInstance().onWaterTempTargetChanged( - std::unique_ptr(new float(atof(payload.c_str())))); + HMIStateProxy::getInstance().onWaterTempTargetChanged(std::make_unique(atof(payload.c_str()))); } } else if (strstr_P(topic.c_str(), HMI_INSTALLATION_CONFIG) != nullptr) { if (strstr_P(payload.c_str(), ENUM_INSTALLATION_THERMODYNAMICS_ONLY) != nullptr) { - HMIStateProxy::getInstance().onInstallationModeChanged( - std::unique_ptr(new HMIInstallation(INST_HP_ONLY))); + HMIStateProxy::getInstance().onInstallationModeChanged(std::make_unique(INST_HP_ONLY)); } else if (strstr_P(payload.c_str(), ENUM_INSTALLATION_SOLAR_BACKUP) != nullptr) { HMIStateProxy::getInstance().onInstallationModeChanged( - std::unique_ptr(new HMIInstallation(INST_HP_AND_SOLAR))); + std::make_unique(INST_HP_AND_SOLAR)); } else if (strstr_P(payload.c_str(), ENUM_INSTALLATION_BOILER_BACKUP_EXT_OPT) != nullptr) { HMIStateProxy::getInstance().onInstallationModeChanged( - std::unique_ptr(new HMIInstallation(INST_HP_AND_EXT_OPT_EXT))); + std::make_unique(INST_HP_AND_EXT_OPT_EXT)); } else if (strstr_P(payload.c_str(), ENUM_INSTALLATION_BOILER_BACKUP_EXT_PRIO) != nullptr) { HMIStateProxy::getInstance().onInstallationModeChanged( - std::unique_ptr(new HMIInstallation(INST_HP_AND_EXT_PRIO_EXT))); + std::make_unique(INST_HP_AND_EXT_PRIO_EXT)); } else if (strstr_P(payload.c_str(), ENUM_INSTALLATION_BOILER_BACKUP_HP_OPT) != nullptr) { HMIStateProxy::getInstance().onInstallationModeChanged( - std::unique_ptr(new HMIInstallation(INST_HP_AND_EXT_OPT_HP))); + std::make_unique(INST_HP_AND_EXT_OPT_HP)); } else if (strstr_P(payload.c_str(), ENUM_INSTALLATION_BOILER_BACKUP_HP_PRIO) != nullptr) { HMIStateProxy::getInstance().onInstallationModeChanged( - std::unique_ptr(new HMIInstallation(INST_HP_AND_EXT_PRIO_HP))); + std::make_unique(INST_HP_AND_EXT_PRIO_HP)); } else { HMIStateProxy::getInstance().onInstallationModeChanged(std::unique_ptr(nullptr)); } } + else if (strstr_P(topic.c_str(), HMI_FAN_EXHAUST_CONFIG) != nullptr) + { + if (strstr_P(payload.c_str(), ENUM_CONFIG_EXHAUST_FAN_STOP) != nullptr) + { + HMIStateProxy::getInstance().onFanExhaustModeChanged(std::make_unique(EXHAUST_STOP)); + } + else if (strstr_P(payload.c_str(), ENUM_CONFIG_EXHAUST_FAN_LOW_SPEED) != nullptr) + { + HMIStateProxy::getInstance().onFanExhaustModeChanged(std::make_unique(EXHAUST_LOW_SPEED)); + } + else if (strstr_P(payload.c_str(), ENUM_CONFIG_EXHAUST_FAN_HIGH_SPEED) != nullptr) + { + HMIStateProxy::getInstance().onFanExhaustModeChanged(std::make_unique(EXHAUST_HIGH_SPEED)); + } + else + { + HMIStateProxy::getInstance().onFanExhaustModeChanged(std::unique_ptr(nullptr)); + } + } + + else if (strstr_P(topic.c_str(), HMI_AIR_DUCT_CONFIG) != nullptr) + { + if (strstr_P(payload.c_str(), ENUM_AIR_DUCT_IN_IN) != nullptr) + { + HMIStateProxy::getInstance().onAirductConfigChanged(std::make_unique(AD_INT_INT)); + } + else if (strstr_P(payload.c_str(), ENUM_AIR_DUCT_INT_EXT) != nullptr) + { + HMIStateProxy::getInstance().onAirductConfigChanged(std::make_unique(AD_INT_EXT)); + } + else if (strstr_P(payload.c_str(), ENUM_AIR_DUCT_EXT_EXT) != nullptr) + { + HMIStateProxy::getInstance().onAirductConfigChanged(std::make_unique(AD_EXT_EXT)); + } + else + { + HMIStateProxy::getInstance().onAirductConfigChanged(std::unique_ptr(nullptr)); + } + } else if ( (strlen(optionalSubscribeTopicSetPvHeatPumpFlag) != 0) @@ -239,8 +269,6 @@ void MQTTTask::spawn() } } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wformat" void MQTTTask::setup() { mMQTTClient.begin(aquamqtt::config::brokerAddr, aquamqtt::config::brokerPort, mWiFiClient); @@ -266,9 +294,9 @@ void MQTTTask::check_mqtt_connection() Serial.println("[mqtt] is disconnected... trying to connect to mqtt broker"); while (!mMQTTClient.connect( - aquamqtt::config::brokerClientId, - strlen(aquamqtt::config::brokerUser) == 0 ? nullptr : aquamqtt::config::brokerUser, - strlen(aquamqtt::config::brokerPassword) == 0 ? nullptr : aquamqtt::config::brokerPassword)) + config::brokerClientId, + strlen(config::brokerUser) == 0 ? nullptr : config::brokerUser, + strlen(config::brokerPassword) == 0 ? nullptr : config::brokerPassword)) { vTaskDelay(pdMS_TO_TICKS(1000)); esp_task_wdt_reset(); @@ -318,49 +346,49 @@ void MQTTTask::loop() if ((notify & 1 << 8) != 0 || fullUpdate) { - if (HMIStateProxy::getInstance().copyFrame(aquamqtt::message::HMI_MESSAGE_IDENTIFIER, mTransferBuffer)) + if (HMIStateProxy::getInstance().copyFrame(HMI_MESSAGE_IDENTIFIER, mTransferBuffer)) { updateHMIStatus(fullUpdate); if (mLastProcessedHMIMessage == nullptr) { - mLastProcessedHMIMessage = new uint8_t[aquamqtt::message::HMI_MESSAGE_LENGTH]; + mLastProcessedHMIMessage = new uint8_t[HMI_MESSAGE_LENGTH]; } - memcpy(mLastProcessedHMIMessage, mTransferBuffer, aquamqtt::message::HMI_MESSAGE_LENGTH); + memcpy(mLastProcessedHMIMessage, mTransferBuffer, HMI_MESSAGE_LENGTH); } } if ((notify & 1 << 7) != 0 || fullUpdate) { - if (MainStateProxy::getInstance().copyFrame(aquamqtt::message::MAIN_MESSAGE_IDENTIFIER, mTransferBuffer)) + if (MainStateProxy::getInstance().copyFrame(MAIN_MESSAGE_IDENTIFIER, mTransferBuffer)) { updateMainStatus(fullUpdate); if (mLastProcessedMainMessage == nullptr) { - mLastProcessedMainMessage = new uint8_t[aquamqtt::message::MAIN_MESSAGE_LENGTH]; + mLastProcessedMainMessage = new uint8_t[MAIN_MESSAGE_LENGTH]; } - memcpy(mLastProcessedMainMessage, mTransferBuffer, aquamqtt::message::MAIN_MESSAGE_LENGTH); + memcpy(mLastProcessedMainMessage, mTransferBuffer, MAIN_MESSAGE_LENGTH); } } if ((notify & 1 << 6) != 0 || fullUpdate) { - if (MainStateProxy::getInstance().copyFrame(aquamqtt::message::ENERGY_MESSAGE_IDENTIFIER, mTransferBuffer)) + if (MainStateProxy::getInstance().copyFrame(ENERGY_MESSAGE_IDENTIFIER, mTransferBuffer)) { updateEnergyStats(fullUpdate); if (mLastProcessedEnergyMessage == nullptr) { - mLastProcessedEnergyMessage = new uint8_t[aquamqtt::message::ENERGY_MESSAGE_LENGTH]; + mLastProcessedEnergyMessage = new uint8_t[ENERGY_MESSAGE_LENGTH]; } - memcpy(mLastProcessedEnergyMessage, mTransferBuffer, aquamqtt::message::ENERGY_MESSAGE_LENGTH); + memcpy(mLastProcessedEnergyMessage, mTransferBuffer, ENERGY_MESSAGE_LENGTH); } } if ((notify & 1 << 5) != 0) { - if (MainStateProxy::getInstance().copyFrame(aquamqtt::message::ERROR_MESSAGE_IDENTIFIER, mTransferBuffer)) + if (MainStateProxy::getInstance().copyFrame(ERROR_MESSAGE_IDENTIFIER, mTransferBuffer)) { updateErrorStatus(); } @@ -387,8 +415,6 @@ void MQTTTask::loop() mMQTTClient.loop(); } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wformat" void MQTTTask::updateStats() { publishString( @@ -433,6 +459,8 @@ void MQTTTask::updateStats() overrideJson[HMI_HEATING_ELEMENT_ENABLED] = overrides.heatingElementEnabled ? "1" : "0"; overrideJson[HMI_EMERGENCY_MODE] = overrides.emergencyModeEnabled ? "1" : "0"; overrideJson[HMI_INSTALLATION_CONFIG] = overrides.installationMode ? "1" : "0"; + overrideJson[HMI_FAN_EXHAUST_CONFIG] = overrides.exhaustFanMode ? "1" : "0"; + overrideJson[HMI_AIR_DUCT_CONFIG] = overrides.airductConfig ? "1" : "0"; overrideJson[HMI_TIME_AND_DATE] = (aquamqtt::config::OVERRIDE_TIME_AND_DATE_IN_MITM && aquamqtt::config::OPERATION_MODE != aquamqtt::config::EOperationMode::LISTENER) @@ -477,10 +505,6 @@ void MQTTTask::updateStats() HMIStateProxy::getInstance().isPVModeHeatElementEnabled()); } } -#pragma clang diagnostic pop - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wformat" void MQTTTask::updateMainStatus(bool fullUpdate) { message::MainStatusMessage message(mTransferBuffer); @@ -584,8 +608,6 @@ void MQTTTask::updateMainStatus(bool fullUpdate) } } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wformat" void MQTTTask::updateHMIStatus(bool fullUpdate) { message::HMIMessage message(mTransferBuffer); @@ -663,6 +685,11 @@ void MQTTTask::updateHMIStatus(bool fullUpdate) publishString(HMI_SUBTOPIC, HMI_INSTALLATION_CONFIG, installationModeStr(message.installationMode())); } + if (message.exhaustFanChanged()) + { + publishString(HMI_SUBTOPIC, HMI_FAN_EXHAUST_CONFIG, exhaustModeStr(message.fanExhaust())); + } + if (message.timerModeOneChanged()) { sprintf(reinterpret_cast(mTopicBuffer), @@ -715,8 +742,6 @@ void MQTTTask::updateHMIStatus(bool fullUpdate) } } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wformat" void MQTTTask::updateEnergyStats(bool fullUpdate) { message::MainEnergyMessage message(mTransferBuffer); diff --git a/MQTT.md b/MQTT.md index 8bf66cc..12db9bf 100644 --- a/MQTT.md +++ b/MQTT.md @@ -47,6 +47,7 @@ Using the prefix, the `$root` topic is created, which is `$prefix/aquamqtt/` and | Heating Element Enabled | `$root/hmi/heatingElementEnabled` | bool | | | | Anti-Legionella Mode | `$root/hmi/antiLegionellaPerMonth` | uint8 | | 0 (off), 1 (once per month), etc | | Configuration AirDuct | `$root/hmi/configAirduct` | Enum | | INT/INT, INT/EXT, EXT/EXT | +| Configuration FanExhaust | `$root/hmi/configFanExhaust ` | Enum | | STOP, LOW SPEED, HIGH SPEED **Note: Only available in AirDuct mode INT/EXT** | | Configuration Installation | `$root/hmi/configInstallation` | Enum | | HEAT PUMP ONLY, BOILER BACKUP / HEAT PUMP PRIORITY, BOILER BACKUP / HEAT PUMP OPTIMIZED, BOILER BACKUP / BOILER OPTIMIZED, BOILER BACKUP / BOILER PRIORITY, HEAT PUMP AND SOLAR BACKUP | | HMI SetupState | `$root/hmi/setupState` | Enum | | OK, PARTIAL RESET, FACTORY RESET | | PV Input Activated | `$root/hmi/pvInputActivated` | bool | | | @@ -129,6 +130,9 @@ the only ones implemented. If you need more overrides, feel free to raise an iss | Operation Mode | `$root/ctrl/operationMode` | Enum | | "`BOOST`" | Overrides the operation mode, may affect the waterTempTarget. For example BOOST and ABSENCE will automatically set the waterTempTarget accordingly. | | Operation Type | `$root/ctrl/operationType` | Enum | | "`ALWAYS ON`" | Overrides the operation type | | Installation Config | `$root/ctrl/configInstallation` | Enum | | "`HEAT PUMP ONLY`", "`BOILER BACKUP / HEAT PUMP PRIORITY"`", "`...`" | Overrides the installation config | +| AirDuct Config | `$root/ctrl/configAirduct` | Enum | | "`INT/INT`", "`INT/EXT`", "`EXT/EXT`" | Overrides the air duct config | +| FanExhaust Config | `$root/ctrl/configFanExhaust` | Enum | | "`STOP`", "`LOW SPEED`", "`HIGH SPEED`" | Overrides the fan exhaust config. **Note: This will only have an effect in AirDuct mode INT/EXT** | + | Enable or disable heating element | `$root/ctrl/heatingElementEnabled` | bool | | "`1`" | Allow the DHW heat pump to use the heating element if needed. Sanity: It is not possible to disable the heating element in case emergency mode is enabled. | | Enable or disable emergency mode | `$root/ctrl/emergencyModeEnabled` | bool | | "`0`" | Forces the DHW heat pump to use only the heating element. Sanity: it is not possible to enable emergency mode if heating element has been disabled. | | Set PV Mode Heat Pump Flag | `$root/ctrl/flagPVModeHeatPump` | bool | | "`1`" | See [README-PV.md](/README-PV.md) additional information. Note: It is possible to define an additional custom mqtt topic for this attribute within `Configuration.h` | diff --git a/PROTOCOL.md b/PROTOCOL.md index 1c14875..ed0d647 100644 --- a/PROTOCOL.md +++ b/PROTOCOL.md @@ -119,7 +119,7 @@ controller completes the packet on the one-wire bus. | 5 | 0 | Anti-Legionella Mode / AirDuct Mode | 0 == Off, 1 == 1perMonth, 2 == 2perMonth, 3 == 3perMonth, 4 == 4/perMonth, // 0 == AirDuct INT/INT, 16 == AirDuct EXT/INT, 32 == AirDuct EXT/EXT | | 6 | 240 | Emergency-Mode, Command: Change Connectivity | "Emergency Mode Off == 240, Emergency Mode On == 241", "Disabled Connectivity: No == 240, Disabled Connectivity: Yes == 16" | | 7 | 17 | InstallationConfig | WP-Only == 0, WP+ExtBoiler-Prio-WP == 1, Wp+ExtBoiler-Opt-WP == 17, Wp+ExtBoiler-Opt-ExtBoiler == 33 , Wp+ExtBoiler-Prio-ExtBoiler == 49 , WP + Solar == 50 | -| 8 | 240 | Command: Change Heat-Exchanger | See Commands | +| 8 | 240 | ExhaustFanConfig, Command: Change Heat-Exchanger | Exhaust Fan Stop == 240, Low Speed == 241, High Speed == 242. See Commands | | 9 | 4 | Heating-Element / SetupState / PV allowed | Heating-Element Automatic-Mode == 4, Heating-Element Disabled == 0, Setup Factory Settings == 164, Setup Airduct Set == 36, Setup Finished == 4 ... and PV allowed but not enabled = 4, PV allowed and enabled = 6 | | 10 | 16 | Timer Mode: Window 1 Start | 16 = 04:00h, 12 = 03:00h | | 11 | 56 | Timer Mode: Window 1 Length | 52 = 13h runtime, 56 = 14h runtime |