Merge pull request #109 from nathanjw/unformat-select

Add vertical and horizontal vane position controls
This commit is contained in:
Geoff Davis 2024-06-23 13:49:30 -07:00 committed by GitHub
commit 2ac56d5a8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 249 additions and 7 deletions

View File

@ -42,6 +42,8 @@ tested by the author on the following units:
* `MSZ-GL06NA`
* `MFZ-KA09NA`
* `MSZ-FH35V`
* `MSZ-LN35VG2W`
## Usage
@ -240,6 +242,11 @@ climate:
- platform: mitsubishi_heatpump
name: "${friendly_name}"
horizontal_vane_select:
name: Horizontal Vane
vertical_vane_select:
name: Vertical Vane
# ESP32 only - change UART0 to UART1 or UART2 and remove the
# logging:baud_rate above to allow the built-in UART0 to function for
# logging.
@ -327,6 +334,11 @@ climate:
- platform: mitsubishi_heatpump
name: "${friendly_name}"
horizontal_vane_select:
name: Horizontal Vane
vertical_vane_select:
name: Vertical Vane
# ESP32 only - change UART0 to UART1 or UART2 and remove the
# logging:baud_rate above to allow the built-in UART0 to function for
# logging.
@ -350,8 +362,7 @@ climate:
supports:
mode: ["HEAT_COOL", "COOL", "HEAT", "FAN_ONLY"]
fan_mode: ["AUTO", "LOW", "MEDIUM", "HIGH"]
swing_mode: ["OFF", "VERTICAL"]
swing_mode: ["OFF", "VERTICAL", "HORIZONTAL", "BOTH"]
visual:
min_temperature: 16
max_temperature: 31
@ -397,6 +408,7 @@ climate:
request wasn't received from your ESPHome controller. This will result
in the heatpump reverting to it's internal temperature sensor if the heatpump
loses it's WiFi connection.
equest.)
## Other configuration

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import climate
from esphome.components import climate, select
from esphome.components.logger import HARDWARE_UART_TO_SERIAL
from esphome.const import (
CONF_ID,
@ -15,12 +15,24 @@ from esphome.const import (
)
from esphome.core import CORE, coroutine
AUTO_LOAD = ["climate"]
AUTO_LOAD = ["climate", "select"]
CONF_SUPPORTS = "supports"
CONF_HORIZONTAL_SWING_SELECT = "horizontal_vane_select"
CONF_VERTICAL_SWING_SELECT = "vertical_vane_select"
DEFAULT_CLIMATE_MODES = ["HEAT_COOL", "COOL", "HEAT", "DRY", "FAN_ONLY"]
DEFAULT_FAN_MODES = ["AUTO", "DIFFUSE", "LOW", "MEDIUM", "MIDDLE", "HIGH"]
DEFAULT_SWING_MODES = ["OFF", "VERTICAL"]
HORIZONTAL_SWING_OPTIONS = [
"auto",
"swing",
"left",
"left_center",
"center",
"right_center",
"right",
]
VERTICAL_SWING_OPTIONS = ["swing", "auto", "up", "up_center", "center", "down_center", "down"]
# Remote temperature timeout configuration
CONF_REMOTE_OPERATING_TIMEOUT = "remote_temperature_operating_timeout_minutes"
@ -31,6 +43,9 @@ MitsubishiHeatPump = cg.global_ns.class_(
"MitsubishiHeatPump", climate.Climate, cg.PollingComponent
)
MitsubishiACSelect = cg.global_ns.class_(
"MitsubishiACSelect", select.Select, cg.Component
)
def valid_uart(uart):
if CORE.is_esp8266:
@ -43,6 +58,10 @@ def valid_uart(uart):
return cv.one_of(*uarts, upper=True)(uart)
SELECT_SCHEMA = select.SELECT_SCHEMA.extend(
{cv.GenerateID(CONF_ID): cv.declare_id(MitsubishiACSelect)}
)
CONFIG_SCHEMA = climate.CLIMATE_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(MitsubishiHeatPump),
@ -58,6 +77,9 @@ CONFIG_SCHEMA = climate.CLIMATE_SCHEMA.extend(
cv.Optional(CONF_UPDATE_INTERVAL, default="500ms"): cv.All(
cv.update_interval, cv.Range(max=cv.TimePeriod(milliseconds=9000))
),
# Add selects for vertical and horizontal vane positions
cv.Optional(CONF_HORIZONTAL_SWING_SELECT): SELECT_SCHEMA,
cv.Optional(CONF_VERTICAL_SWING_SELECT): SELECT_SCHEMA,
# Optionally override the supported ClimateTraits.
cv.Optional(CONF_SUPPORTS, default={}): cv.Schema(
{
@ -113,6 +135,18 @@ def to_code(config):
climate.CLIMATE_SWING_MODES[mode]
))
if CONF_HORIZONTAL_SWING_SELECT in config:
conf = config[CONF_HORIZONTAL_SWING_SELECT]
swing_select = yield select.new_select(conf, options=HORIZONTAL_SWING_OPTIONS)
yield cg.register_component(swing_select, conf)
cg.add(var.set_horizontal_vane_select(swing_select))
if CONF_VERTICAL_SWING_SELECT in config:
conf = config[CONF_VERTICAL_SWING_SELECT]
swing_select = yield select.new_select(conf, options=VERTICAL_SWING_OPTIONS)
yield cg.register_component(swing_select, conf)
cg.add(var.set_vertical_vane_select(swing_select))
yield cg.register_component(var, config)
yield climate.register_climate(var, config)
cg.add_library(

View File

@ -111,6 +111,117 @@ climate::ClimateTraits& MitsubishiHeatPump::config_traits() {
return traits_;
}
void MitsubishiHeatPump::update_swing_horizontal(const std::string &swing) {
this->horizontal_swing_state_ = swing;
if (this->horizontal_vane_select_ != nullptr &&
this->horizontal_vane_select_->state != this->horizontal_swing_state_) {
this->horizontal_vane_select_->publish_state(
this->horizontal_swing_state_); // Set current horizontal swing
// position
}
}
void MitsubishiHeatPump::update_swing_vertical(const std::string &swing) {
this->vertical_swing_state_ = swing;
if (this->vertical_vane_select_ != nullptr &&
this->vertical_vane_select_->state != this->vertical_swing_state_) {
this->vertical_vane_select_->publish_state(
this->vertical_swing_state_); // Set current vertical swing position
}
}
void MitsubishiHeatPump::set_vertical_vane_select(
select::Select *vertical_vane_select) {
this->vertical_vane_select_ = vertical_vane_select;
this->vertical_vane_select_->add_on_state_callback(
[this](const std::string &value, size_t index) {
if (value == this->vertical_swing_state_) return;
this->on_vertical_swing_change(value);
});
}
void MitsubishiHeatPump::set_horizontal_vane_select(
select::Select *horizontal_vane_select) {
this->horizontal_vane_select_ = horizontal_vane_select;
this->horizontal_vane_select_->add_on_state_callback(
[this](const std::string &value, size_t index) {
if (value == this->horizontal_swing_state_) return;
this->on_horizontal_swing_change(value);
});
}
void MitsubishiHeatPump::on_vertical_swing_change(const std::string &swing) {
ESP_LOGD(TAG, "Setting vertical swing position");
bool updated = false;
if (swing == "swing") {
hp->setVaneSetting("SWING");
updated = true;
} else if (swing == "auto") {
hp->setVaneSetting("AUTO");
updated = true;
} else if (swing == "up") {
hp->setVaneSetting("1");
updated = true;
} else if (swing == "up_center") {
hp->setVaneSetting("2");
updated = true;
} else if (swing == "center") {
hp->setVaneSetting("3");
updated = true;
} else if (swing == "down_center") {
hp->setVaneSetting("4");
updated = true;
} else if (swing == "down") {
hp->setVaneSetting("5");
updated = true;
} else {
ESP_LOGW(TAG, "Invalid vertical vane position %s", swing);
}
ESP_LOGD(TAG, "Vertical vane - Was HeatPump updated? %s", YESNO(updated));
// and the heat pump:
hp->update();
}
void MitsubishiHeatPump::on_horizontal_swing_change(const std::string &swing) {
ESP_LOGD(TAG, "Setting horizontal swing position");
bool updated = false;
if (swing == "swing") {
hp->setWideVaneSetting("SWING");
updated = true;
} else if (swing == "auto") {
hp->setWideVaneSetting("<>");
updated = true;
} else if (swing == "left") {
hp->setWideVaneSetting("<<");
updated = true;
} else if (swing == "left_center") {
hp->setWideVaneSetting("<");
updated = true;
} else if (swing == "center") {
hp->setWideVaneSetting("|");
updated = true;
} else if (swing == "right_center") {
hp->setWideVaneSetting(">");
updated = true;
} else if (swing == "right") {
hp->setWideVaneSetting(">>");
updated = true;
} else {
ESP_LOGW(TAG, "Invalid horizontal vane position %s", swing);
}
ESP_LOGD(TAG, "Horizontal vane - Was HeatPump updated? %s", YESNO(updated));
// and the heat pump:
hp->update();
}
/**
* Implement control of a MitsubishiHeatPump.
*
@ -264,10 +375,22 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) {
switch(*call.get_swing_mode()) {
case climate::CLIMATE_SWING_OFF:
hp->setVaneSetting("AUTO");
hp->setWideVaneSetting("|");
updated = true;
break;
case climate::CLIMATE_SWING_VERTICAL:
hp->setVaneSetting("SWING");
hp->setWideVaneSetting("|");
updated = true;
break;
case climate::CLIMATE_SWING_HORIZONTAL:
hp->setVaneSetting("3");
hp->setWideVaneSetting("SWING");
updated = true;
break;
case climate::CLIMATE_SWING_BOTH:
hp->setVaneSetting("SWING");
hp->setWideVaneSetting("SWING");
updated = true;
break;
default:
@ -370,15 +493,52 @@ void MitsubishiHeatPump::hpSettingsChanged() {
/* ******** HANDLE MITSUBISHI VANE CHANGES ********
* const char* VANE_MAP[7] = {"AUTO", "1", "2", "3", "4", "5", "SWING"};
*/
if (strcmp(currentSettings.vane, "SWING") == 0) {
if (strcmp(currentSettings.vane, "SWING") == 0 &&
strcmp(currentSettings.wideVane, "SWING") == 0) {
this->swing_mode = climate::CLIMATE_SWING_BOTH;
} else if (strcmp(currentSettings.vane, "SWING") == 0) {
this->swing_mode = climate::CLIMATE_SWING_VERTICAL;
}
else {
} else if (strcmp(currentSettings.wideVane, "SWING") == 0) {
this->swing_mode = climate::CLIMATE_SWING_HORIZONTAL;
} else {
this->swing_mode = climate::CLIMATE_SWING_OFF;
}
ESP_LOGI(TAG, "Swing mode is: %i", this->swing_mode);
if (strcmp(currentSettings.vane, "SWING") == 0) {
this->update_swing_vertical("swing");
} else if (strcmp(currentSettings.vane, "AUTO") == 0) {
this->update_swing_vertical("auto");
} else if (strcmp(currentSettings.vane, "1") == 0) {
this->update_swing_vertical("up");
} else if (strcmp(currentSettings.vane, "2") == 0) {
this->update_swing_vertical("up_center");
} else if (strcmp(currentSettings.vane, "3") == 0) {
this->update_swing_vertical("center");
} else if (strcmp(currentSettings.vane, "4") == 0) {
this->update_swing_vertical("down_center");
} else if (strcmp(currentSettings.vane, "5") == 0) {
this->update_swing_vertical("down");
}
ESP_LOGI(TAG, "Vertical vane mode is: %s", currentSettings.vane);
if (strcmp(currentSettings.wideVane, "SWING") == 0) {
this->update_swing_horizontal("swing");
} else if (strcmp(currentSettings.wideVane, "<>") == 0) {
this->update_swing_horizontal("auto");
} else if (strcmp(currentSettings.wideVane, "<<") == 0) {
this->update_swing_horizontal("left");
} else if (strcmp(currentSettings.wideVane, "<") == 0) {
this->update_swing_horizontal("left_center");
} else if (strcmp(currentSettings.wideVane, "|") == 0) {
this->update_swing_horizontal("center");
} else if (strcmp(currentSettings.wideVane, ">") == 0) {
this->update_swing_horizontal("right_center");
} else if (strcmp(currentSettings.wideVane, ">>") == 0) {
this->update_swing_horizontal("right");
}
ESP_LOGI(TAG, "Horizontal vane mode is: %s", currentSettings.wideVane);
/*
* ******** HANDLE TARGET TEMPERATURE CHANGES ********
@ -525,6 +685,8 @@ void MitsubishiHeatPump::setup() {
this->target_temperature = NAN;
this->fan_mode = climate::CLIMATE_FAN_OFF;
this->swing_mode = climate::CLIMATE_SWING_OFF;
this->vertical_swing_state_ = "auto";
this->horizontal_swing_state_ = "auto";
#ifdef USE_CALLBACKS
hp->setSettingsChangedCallback(

View File

@ -18,6 +18,7 @@
#define USE_CALLBACKS
#include "esphome.h"
#include "esphome/components/select/select.h"
#include "esphome/core/preferences.h"
#include <chrono>
@ -100,6 +101,9 @@ class MitsubishiHeatPump : public esphome::PollingComponent, public esphome::cli
// set_remote_temp(0) to switch back to the internal sensor.
void set_remote_temperature(float);
void set_vertical_vane_select(esphome::select::Select *vertical_vane_select);
void set_horizontal_vane_select(esphome::select::Select *horizontal_vane_select);
// Used to validate that a connection is present between the controller
// and this heatpump.
void ping();
@ -123,6 +127,12 @@ class MitsubishiHeatPump : public esphome::PollingComponent, public esphome::cli
// The ClimateTraits supported by this HeatPump.
esphome::climate::ClimateTraits traits_;
// Vane position
void update_swing_horizontal(const std::string &swing);
void update_swing_vertical(const std::string &swing);
std::string vertical_swing_state_;
std::string horizontal_swing_state_;
// Allow the HeatPump class to use get_hw_serial_
friend class HeatPump;
@ -148,6 +158,15 @@ class MitsubishiHeatPump : public esphome::PollingComponent, public esphome::cli
static void save(float value, esphome::ESPPreferenceObject& storage);
static esphome::optional<float> load(esphome::ESPPreferenceObject& storage);
esphome::select::Select *vertical_vane_select_ =
nullptr; // Select to store manual position of vertical swing
esphome::select::Select *horizontal_vane_select_ =
nullptr; // Select to store manual position of horizontal swing
// When received command to change the vane positions
void on_horizontal_swing_change(const std::string &swing);
void on_vertical_swing_change(const std::string &swing);
static void log_packet(byte* packet, unsigned int length, char* packetDirection);
private:

View File

@ -0,0 +1,15 @@
#pragma once
#include "esphome/components/select/select.h"
#include "esphome/core/component.h"
namespace esphome {
class MitsubishiACSelect : public select::Select, public Component {
protected:
void control(const std::string &value) override {
this->publish_state(value);
}
};
} // namespace esphome