From 9515257c8b8d17c8a3d3ac862373bfecc87b4779 Mon Sep 17 00:00:00 2001 From: Phil Genera Date: Thu, 4 Jun 2020 20:26:56 -0400 Subject: [PATCH 1/9] Store setpoints per-mode to make selection work like the IR remote. --- espmhp.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- espmhp.h | 16 ++++++++++++++- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/espmhp.cpp b/espmhp.cpp index 5d256d1..ad27746 100644 --- a/espmhp.cpp +++ b/espmhp.cpp @@ -102,17 +102,26 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) { ESP_LOGV(TAG, "Control called."); bool updated = false; + bool has_temp = call.get_target_temperature().has_value(); if (call.get_mode().has_value()){ this->mode = *call.get_mode(); switch (*call.get_mode()) { case climate::CLIMATE_MODE_COOL: hp->setModeSetting("COOL"); hp->setPowerSetting("ON"); + if (cool_setpoint.has_value() && !has_temp) { + hp->setTemperature(cool_setpoint.value()); + this->target_temperature = cool_setpoint.value(); + } updated = true; break; case climate::CLIMATE_MODE_HEAT: hp->setModeSetting("HEAT"); hp->setPowerSetting("ON"); + if (heat_setpoint.has_value() && !has_temp) { + hp->setTemperature(heat_setpoint.value()); + this->target_temperature = heat_setpoint.value(); + } updated = true; break; case climate::CLIMATE_MODE_DRY: @@ -123,6 +132,10 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) { case climate::CLIMATE_MODE_AUTO: hp->setModeSetting("AUTO"); hp->setPowerSetting("ON"); + if (auto_setpoint.has_value() && !has_temp) { + hp->setTemperature(auto_setpoint.value()); + this->target_temperature = auto_setpoint.value(); + } updated = true; break; case climate::CLIMATE_MODE_FAN_ONLY: @@ -138,11 +151,11 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) { } } - if (call.get_target_temperature().has_value()){ + if (has_temp){ ESP_LOGV( "control", "Sending target temp: %.1f", *call.get_target_temperature() - ) + ); hp->setTemperature(*call.get_target_temperature()); this->target_temperature = *call.get_target_temperature(); updated = true; @@ -239,14 +252,26 @@ void MitsubishiHeatPump::hpSettingsChanged() { if (strcmp(currentSettings.power, "ON") == 0) { if (strcmp(currentSettings.mode, "HEAT") == 0) { this->mode = climate::CLIMATE_MODE_HEAT; + if (heat_setpoint != currentSettings.temperature) { + heat_setpoint = currentSettings.temperature; + save(currentSettings.temperature, heat_storage); + } } else if (strcmp(currentSettings.mode, "DRY") == 0) { this->mode = climate::CLIMATE_MODE_DRY; } else if (strcmp(currentSettings.mode, "COOL") == 0) { this->mode = climate::CLIMATE_MODE_COOL; + if (cool_setpoint != currentSettings.temperature) { + cool_setpoint = currentSettings.temperature; + save(currentSettings.temperature, cool_storage); + } } else if (strcmp(currentSettings.mode, "FAN") == 0) { this->mode = climate::CLIMATE_MODE_FAN_ONLY; } else if (strcmp(currentSettings.mode, "AUTO") == 0) { this->mode = climate::CLIMATE_MODE_AUTO; + if (auto_setpoint != currentSettings.temperature) { + auto_setpoint = currentSettings.temperature; + save(currentSettings.temperature, auto_storage); + } } else { ESP_LOGW( TAG, @@ -397,14 +422,45 @@ void MitsubishiHeatPump::setup() { this->mark_failed(); } + // create various setpoint persistence: + cool_storage = global_preferences.make_preference(this->get_object_id_hash() + 1); + heat_storage = global_preferences.make_preference(this->get_object_id_hash() + 2); + auto_storage = global_preferences.make_preference(this->get_object_id_hash() + 3); + + // load values from storage: + cool_setpoint = load(cool_storage); + heat_setpoint = load(heat_storage); + auto_setpoint = load(auto_storage); + this->dump_config(); } +/** + * The ESP only has a few bytes of rtc storage, so instead + * of storing floats directly, we'll store the number of + * TEMPERATURE_STEPs from MIN_TEMPERATURE. + **/ +void MitsubishiHeatPump::save(float value, ESPPreferenceObject& storage) { + uint8_t steps = (value - ESPMHP_MIN_TEMPERATURE) / ESPMHP_TEMPERATURE_STEP; + storage.save(&steps); +} + +optional MitsubishiHeatPump::load(ESPPreferenceObject& storage) { + uint8_t steps = 0; + if (!storage.load(&steps)) { + return {}; + } + return ESPMHP_MIN_TEMPERATURE + (steps * ESPMHP_TEMPERATURE_STEP); +} + void MitsubishiHeatPump::dump_config() { this->banner(); ESP_LOGI(TAG, " Supports HEAT: %s", YESNO(true)); ESP_LOGI(TAG, " Supports COOL: %s", YESNO(true)); ESP_LOGI(TAG, " Supports AWAY mode: %s", YESNO(false)); + ESP_LOGI(TAG, " Saved heat: %.1f", heat_setpoint.value_or(-1)); + ESP_LOGI(TAG, " Saved cool: %.1f", cool_setpoint.value_or(-1)); + ESP_LOGI(TAG, " Saved auto: %.1f", auto_setpoint.value_or(-1)); } void MitsubishiHeatPump::dump_state() { diff --git a/espmhp.h b/espmhp.h index d387c4e..15e04f3 100644 --- a/espmhp.h +++ b/espmhp.h @@ -15,6 +15,8 @@ #define USE_CALLBACKS #include "esphome.h" +#include "esphome/core/preferences.h" + #include "HeatPump.h" using namespace esphome; @@ -36,7 +38,6 @@ static const uint8_t ESPMHP_MAX_TEMPERATURE = 31; // degrees C, static const float ESPMHP_TEMPERATURE_STEP = 0.5; // temperature setting step, // in degrees C - class MitsubishiHeatPump : public PollingComponent, public climate::Climate { public: @@ -99,6 +100,19 @@ class MitsubishiHeatPump : public PollingComponent, public climate::Climate { //ESP8266 or UART0 on ESP32 void check_logger_conflict_(); + // various prefs to save mode-specific temperatures, akin to how the IR + // remote works. + ESPPreferenceObject cool_storage; + ESPPreferenceObject heat_storage; + ESPPreferenceObject auto_storage; + + optional cool_setpoint; + optional heat_setpoint; + optional auto_setpoint; + + static void save(float value, ESPPreferenceObject& storage); + static optional load(ESPPreferenceObject& storage); + private: // Retrieve the HardwareSerial pointer from friend and subclasses. HardwareSerial *hw_serial_; From 4b3675168b699f6e52bd54ecde94c5b3aefdcaf9 Mon Sep 17 00:00:00 2001 From: Phil Genera Date: Sat, 6 Jun 2020 08:11:19 -0400 Subject: [PATCH 2/9] Get running state from hp instead of computing --- espmhp.cpp | 59 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/espmhp.cpp b/espmhp.cpp index 5d256d1..b8ef552 100644 --- a/espmhp.cpp +++ b/espmhp.cpp @@ -142,7 +142,7 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) { ESP_LOGV( "control", "Sending target temp: %.1f", *call.get_target_temperature() - ) + ); hp->setTemperature(*call.get_target_temperature()); this->target_temperature = *call.get_target_temperature(); updated = true; @@ -302,33 +302,6 @@ void MitsubishiHeatPump::hpSettingsChanged() { this->target_temperature = currentSettings.temperature; ESP_LOGI(TAG, "Target temp is: %f", this->target_temperature); - - /* - * Compute running state from mode & temperatures - */ - switch (this->mode) { - case climate::CLIMATE_MODE_HEAT: - if (this->current_temperature < this->target_temperature) { - this->action = climate::CLIMATE_ACTION_HEATING; - } - else { - this->action = climate::CLIMATE_ACTION_IDLE; - } - break; - case climate::CLIMATE_MODE_COOL: - if (this->current_temperature > this->target_temperature) { - this->action = climate::CLIMATE_ACTION_COOLING; - } - else { - this->action = climate::CLIMATE_ACTION_IDLE; - } - break; - case climate::CLIMATE_MODE_DRY: - this->action = climate::CLIMATE_ACTION_DRYING; - default: - this->action = climate::CLIMATE_ACTION_OFF; - } - /* * ******** Publish state back to ESPHome. ******** */ @@ -340,6 +313,36 @@ void MitsubishiHeatPump::hpSettingsChanged() { */ void MitsubishiHeatPump::hpStatusChanged(heatpumpStatus currentStatus) { this->current_temperature = currentStatus.roomTemperature; + switch (this->mode) { + case climate::CLIMATE_MODE_HEAT: + if (currentStatus.operating) { + this->action = climate::CLIMATE_ACTION_HEATING; + } + else { + this->action = climate::CLIMATE_ACTION_IDLE; + } + break; + case climate::CLIMATE_MODE_COOL: + if (currentStatus.operating) { + this->action = climate::CLIMATE_ACTION_COOLING; + } + else { + this->action = climate::CLIMATE_ACTION_IDLE; + } + break; + case climate::CLIMATE_MODE_DRY: + if (currentStatus.operating) { + this->action = climate::CLIMATE_ACTION_DRYING; + } + else { + this->action = climate::CLIMATE_ACTION_IDLE; + } + case climate::CLIMATE_MODE_FAN_ONLY: + this->action = climate::CLIMATE_ACTION_FAN; + default: + this->action = climate::CLIMATE_ACTION_OFF; + } + this->publish_state(); } From a36cb30a89dc41ca663e73bedfa799415984a16a Mon Sep 17 00:00:00 2001 From: Phil Genera Date: Sat, 6 Jun 2020 08:48:10 -0400 Subject: [PATCH 3/9] assume fan running when switching to fan mode --- espmhp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/espmhp.cpp b/espmhp.cpp index b8ef552..0f61188 100644 --- a/espmhp.cpp +++ b/espmhp.cpp @@ -128,6 +128,7 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) { case climate::CLIMATE_MODE_FAN_ONLY: hp->setModeSetting("FAN"); hp->setPowerSetting("ON"); + this->action = climate::CLIMATE_ACTION_FAN; updated = true; break; case climate::CLIMATE_MODE_OFF: @@ -247,6 +248,7 @@ void MitsubishiHeatPump::hpSettingsChanged() { this->mode = climate::CLIMATE_MODE_FAN_ONLY; } else if (strcmp(currentSettings.mode, "AUTO") == 0) { this->mode = climate::CLIMATE_MODE_AUTO; + this->action = climate::CLIMATE_ACTION_FAN; } else { ESP_LOGW( TAG, From bf9259ce0a002d23384f524f4725bc18599d9f0c Mon Sep 17 00:00:00 2001 From: Phil Genera Date: Sat, 6 Jun 2020 08:54:39 -0400 Subject: [PATCH 4/9] off by one branch --- espmhp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/espmhp.cpp b/espmhp.cpp index 0f61188..e4117cf 100644 --- a/espmhp.cpp +++ b/espmhp.cpp @@ -246,9 +246,9 @@ void MitsubishiHeatPump::hpSettingsChanged() { this->mode = climate::CLIMATE_MODE_COOL; } else if (strcmp(currentSettings.mode, "FAN") == 0) { this->mode = climate::CLIMATE_MODE_FAN_ONLY; + this->action = climate::CLIMATE_ACTION_FAN; } else if (strcmp(currentSettings.mode, "AUTO") == 0) { this->mode = climate::CLIMATE_MODE_AUTO; - this->action = climate::CLIMATE_ACTION_FAN; } else { ESP_LOGW( TAG, From 7e91b6bdae1038bf96faea36420df16c01679a87 Mon Sep 17 00:00:00 2001 From: Phil Genera Date: Sat, 6 Jun 2020 09:17:40 -0400 Subject: [PATCH 5/9] Fix missing breaks and have slightly more optimism on mode changes --- espmhp.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/espmhp.cpp b/espmhp.cpp index e4117cf..23637f5 100644 --- a/espmhp.cpp +++ b/espmhp.cpp @@ -118,6 +118,7 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) { case climate::CLIMATE_MODE_DRY: hp->setModeSetting("DRY"); hp->setPowerSetting("ON"); + this->action = climate::CLIMATE_ACTION_DRYING; updated = true; break; case climate::CLIMATE_MODE_AUTO: @@ -242,6 +243,7 @@ void MitsubishiHeatPump::hpSettingsChanged() { this->mode = climate::CLIMATE_MODE_HEAT; } else if (strcmp(currentSettings.mode, "DRY") == 0) { this->mode = climate::CLIMATE_MODE_DRY; + this->action = climate::CLIMATE_ACTION_DRYING; } else if (strcmp(currentSettings.mode, "COOL") == 0) { this->mode = climate::CLIMATE_MODE_COOL; } else if (strcmp(currentSettings.mode, "FAN") == 0) { @@ -334,13 +336,15 @@ void MitsubishiHeatPump::hpStatusChanged(heatpumpStatus currentStatus) { break; case climate::CLIMATE_MODE_DRY: if (currentStatus.operating) { - this->action = climate::CLIMATE_ACTION_DRYING; + this->action = climate::CLIMATE_ACTION_DRYING; } else { this->action = climate::CLIMATE_ACTION_IDLE; } + break; case climate::CLIMATE_MODE_FAN_ONLY: this->action = climate::CLIMATE_ACTION_FAN; + break; default: this->action = climate::CLIMATE_ACTION_OFF; } From 7a9ad8541421743dc3ed2816b37b142e0c9eb1c1 Mon Sep 17 00:00:00 2001 From: Phil Genera Date: Sat, 6 Jun 2020 09:40:54 -0400 Subject: [PATCH 6/9] Naive auto mode action support --- espmhp.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/espmhp.cpp b/espmhp.cpp index 23637f5..f5fbc37 100644 --- a/espmhp.cpp +++ b/espmhp.cpp @@ -108,11 +108,13 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) { case climate::CLIMATE_MODE_COOL: hp->setModeSetting("COOL"); hp->setPowerSetting("ON"); + this->action = climate::CLIMATE_ACTION_IDLE; updated = true; break; case climate::CLIMATE_MODE_HEAT: hp->setModeSetting("HEAT"); hp->setPowerSetting("ON"); + this->action = climate::CLIMATE_ACTION_IDLE; updated = true; break; case climate::CLIMATE_MODE_DRY: @@ -124,6 +126,7 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) { case climate::CLIMATE_MODE_AUTO: hp->setModeSetting("AUTO"); hp->setPowerSetting("ON"); + this->action = climate::CLIMATE_ACTION_IDLE; updated = true; break; case climate::CLIMATE_MODE_FAN_ONLY: @@ -241,16 +244,19 @@ void MitsubishiHeatPump::hpSettingsChanged() { if (strcmp(currentSettings.power, "ON") == 0) { if (strcmp(currentSettings.mode, "HEAT") == 0) { this->mode = climate::CLIMATE_MODE_HEAT; + this->action = climate::CLIMATE_ACTION_IDLE; } else if (strcmp(currentSettings.mode, "DRY") == 0) { this->mode = climate::CLIMATE_MODE_DRY; this->action = climate::CLIMATE_ACTION_DRYING; } else if (strcmp(currentSettings.mode, "COOL") == 0) { this->mode = climate::CLIMATE_MODE_COOL; + this->action = climate::CLIMATE_ACTION_IDLE; } else if (strcmp(currentSettings.mode, "FAN") == 0) { this->mode = climate::CLIMATE_MODE_FAN_ONLY; this->action = climate::CLIMATE_ACTION_FAN; } else if (strcmp(currentSettings.mode, "AUTO") == 0) { this->mode = climate::CLIMATE_MODE_AUTO; + this->action = climate::CLIMATE_ACTION_IDLE; } else { ESP_LOGW( TAG, @@ -334,6 +340,16 @@ void MitsubishiHeatPump::hpStatusChanged(heatpumpStatus currentStatus) { this->action = climate::CLIMATE_ACTION_IDLE; } break; + case climate::CLIMATE_MODE_AUTO: + this->action = climate::CLIMATE_ACTION_IDLE; + if (currentStatus.operating) { + if (this->current_temperature > this->target_temperature) { + this->action = climate::CLIMATE_ACTION_COOLING; + } else if (this->current_temperature < this->target_temperature) { + this->action = climate::CLIMATE_ACTION_HEATING; + } + } + break; case climate::CLIMATE_MODE_DRY: if (currentStatus.operating) { this->action = climate::CLIMATE_ACTION_DRYING; From 41579d226cf5a93f2b66bb93ab52cd84d0f4e136 Mon Sep 17 00:00:00 2001 From: Phil Genera Date: Sat, 6 Jun 2020 11:41:28 -0400 Subject: [PATCH 7/9] Also be optimistic when turning off --- espmhp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/espmhp.cpp b/espmhp.cpp index f5fbc37..b46f9ea 100644 --- a/espmhp.cpp +++ b/espmhp.cpp @@ -138,6 +138,7 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) { case climate::CLIMATE_MODE_OFF: default: hp->setPowerSetting("OFF"); + this->action = climate::CLIMATE_ACTION_OFF; updated = true; break; } @@ -266,6 +267,7 @@ void MitsubishiHeatPump::hpSettingsChanged() { } } else { this->mode = climate::CLIMATE_MODE_OFF; + this->action = climate::CLIMATE_ACTION_OFF; } ESP_LOGI(TAG, "Climate mode is: %i", this->mode); From 8fbf0ecc9810abe0016d7e783d559f4bd810ba7b Mon Sep 17 00:00:00 2001 From: am-io <59386553+am-io@users.noreply.github.com> Date: Sun, 28 Jun 2020 14:33:39 +1000 Subject: [PATCH 8/9] Fix fan speed control --- espmhp.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/espmhp.cpp b/espmhp.cpp index 5d256d1..bc1bde3 100644 --- a/espmhp.cpp +++ b/espmhp.cpp @@ -81,7 +81,7 @@ climate::ClimateTraits MitsubishiHeatPump::traits() { traits.set_supports_fan_mode_off(false); traits.set_supports_fan_mode_auto(true); traits.set_supports_fan_mode_focus(false); - traits.set_supports_fan_mode_diffuse(false); + traits.set_supports_fan_mode_diffuse(true); traits.set_supports_fan_mode_low(true); traits.set_supports_fan_mode_medium(true); traits.set_supports_fan_mode_middle(true); @@ -158,23 +158,23 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) { updated = true; break; case climate::CLIMATE_FAN_DIFFUSE: - hp->setPowerSetting("QUIET"); + hp->setFanSpeed("QUIET"); updated = true; break; case climate::CLIMATE_FAN_LOW: - hp->setPowerSetting("1"); + hp->setFanSpeed("1"); updated = true; break; case climate::CLIMATE_FAN_MEDIUM: - hp->setPowerSetting("2"); + hp->setFanSpeed("2"); updated = true; break; case climate::CLIMATE_FAN_MIDDLE: - hp->setPowerSetting("3"); + hp->setFanSpeed("3"); updated = true; break; case climate::CLIMATE_FAN_HIGH: - hp->setPowerSetting("4"); + hp->setFanSpeed("4"); updated = true; break; case climate::CLIMATE_FAN_ON: From 655ca2ac0f7fc126bc18658e1c1acaa8fa92ea81 Mon Sep 17 00:00:00 2001 From: loongyh Date: Mon, 6 Jul 2020 07:44:48 +0800 Subject: [PATCH 9/9] Don't treat swing mode 'auto' as CLIMATE_SWING_VERTICAL --- espmhp.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/espmhp.cpp b/espmhp.cpp index 5d256d1..ac64699 100644 --- a/espmhp.cpp +++ b/espmhp.cpp @@ -283,10 +283,7 @@ void MitsubishiHeatPump::hpSettingsChanged() { /* ******** HANDLE MITSUBISHI VANE CHANGES ******** * const char* VANE_MAP[7] = {"AUTO", "1", "2", "3", "4", "5", "SWING"}; */ - if ( - (strcmp(currentSettings.vane, "AUTO") == 0) - || (strcmp(currentSettings.vane, "SWING") == 0) - ) { + if (strcmp(currentSettings.vane, "SWING") == 0) { this->swing_mode = climate::CLIMATE_SWING_VERTICAL; } else {