Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kumo Emulation Mode #30

Merged
merged 15 commits into from
Jun 25, 2024
58 changes: 50 additions & 8 deletions esphome/components/mitsubishi_itp/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from esphome.components import (
climate,
uart,
time,
sensor,
binary_sensor,
button,
Expand All @@ -19,11 +20,13 @@
CONF_SUPPORTED_MODES,
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_FREQUENCY,
DEVICE_CLASS_HUMIDITY,
ENTITY_CATEGORY_CONFIG,
ENTITY_CATEGORY_NONE,
STATE_CLASS_MEASUREMENT,
UNIT_CELSIUS,
UNIT_HERTZ,
UNIT_PERCENT,
)
from esphome.core import coroutine

Expand All @@ -36,21 +39,20 @@
"binary_sensor",
"button",
"text_sensor",
"time",
]
DEPENDENCIES = [
"uart",
"climate",
"sensor",
"binary_sensor",
"button",
"text_sensor",
"select",
]

CONF_UART_HEATPUMP = "uart_heatpump"
CONF_UART_THERMOSTAT = "uart_thermostat"
CONF_TIME_SOURCE = "time_source"

CONF_THERMOSTAT_TEMPERATURE = "thermostat_temperature"
CONF_THERMOSTAT_HUMIDITY = "thermostat_humidity"
CONF_THERMOSTAT_BATTERY = "thermostat_battery"
CONF_ERROR_CODE = "error_code"
CONF_ISEE_STATUS = "isee_status"

Expand All @@ -67,6 +69,9 @@
)

CONF_DISABLE_ACTIVE_MODE = "disable_active_mode"
CONF_ENHANCED_MHK_SUPPORT = (
"enhanced_mhk" # EXPERIMENTAL. Will be set to default eventually.
)

DEFAULT_POLLING_INTERVAL = "5s"

Expand Down Expand Up @@ -104,6 +109,7 @@
cv.GenerateID(CONF_ID): cv.declare_id(MitsubishiUART),
cv.Required(CONF_UART_HEATPUMP): cv.use_id(uart.UARTComponent),
cv.Optional(CONF_UART_THERMOSTAT): cv.use_id(uart.UARTComponent),
cv.Optional(CONF_TIME_SOURCE): cv.use_id(time.RealTimeClock),
# Overwrite name from ENTITY_BASE_SCHEMA with "Climate" as default
cv.Optional(CONF_NAME, default="Climate"): cv.Any(
cv.All(
Expand All @@ -127,6 +133,7 @@
cv.use_id(sensor.Sensor)
),
cv.Optional(CONF_DISABLE_ACTIVE_MODE, default=False): cv.boolean,
cv.Optional(CONF_ENHANCED_MHK_SUPPORT, default=False): cv.boolean,
}
).extend(cv.polling_component_schema(DEFAULT_POLLING_INTERVAL))

Expand Down Expand Up @@ -154,6 +161,23 @@
),
sensor.register_sensor,
),
CONF_THERMOSTAT_HUMIDITY: (
"Thermostat Humidity",
sensor.sensor_schema(
unit_of_measurement=UNIT_PERCENT,
device_class=DEVICE_CLASS_HUMIDITY,
state_class=STATE_CLASS_MEASUREMENT,
accuracy_decimals=0,
),
sensor.register_sensor,
),
CONF_THERMOSTAT_BATTERY: (
"Thermostat Battery",
text_sensor.text_sensor_schema(
icon="mdi:battery",
),
text_sensor.register_text_sensor,
),
"compressor_frequency": (
"Compressor Frequency",
sensor.sensor_schema(
Expand Down Expand Up @@ -308,8 +332,16 @@ async def to_code(config):
# Add sensor as source
SELECTS[CONF_TEMPERATURE_SOURCE_SELECT][2].append("Thermostat")

# Traits
# If RTC defined
if CONF_TIME_SOURCE in config:
rtc_component = await cg.get_variable(config[CONF_TIME_SOURCE])
cg.add(getattr(muart_component, "set_time_source")(rtc_component))
elif CONF_UART_THERMOSTAT in config and config.get(CONF_ENHANCED_MHK_SUPPORT):
raise cv.RequiredFieldInvalid(
f"{CONF_TIME_SOURCE} is required if {CONF_ENHANCED_MHK_SUPPORT} is set."
)

# Traits
traits = muart_component.config_traits()

if CONF_SUPPORTED_MODES in config:
Expand All @@ -329,8 +361,13 @@ async def to_code(config):
registration_function,
) in SENSORS.items():
# Only add the thermostat temp if we have a TS_UART
if (sensor_designator == CONF_THERMOSTAT_TEMPERATURE) and (
CONF_UART_THERMOSTAT not in config
if (CONF_UART_THERMOSTAT not in config) and (
sensor_designator
in [
CONF_THERMOSTAT_TEMPERATURE,
CONF_THERMOSTAT_HUMIDITY,
CONF_THERMOSTAT_BATTERY,
]
):
continue

Expand Down Expand Up @@ -390,3 +427,8 @@ async def to_code(config):
# Debug Settings
if dam_conf := config.get(CONF_DISABLE_ACTIVE_MODE):
cg.add(getattr(muart_component, "set_active_mode")(not dam_conf))

if enhanced_mhk_protocol := config.get(CONF_ENHANCED_MHK_SUPPORT):
cg.add(
getattr(muart_component, "set_enhanced_mhk_support")(enhanced_mhk_protocol)
)
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,28 @@ void MitsubishiUART::control(const climate::ClimateCall &call) {
if (call.get_target_temperature().has_value()) {
target_temperature = call.get_target_temperature().value();
set_request_packet.set_target_temperature(call.get_target_temperature().value());

// update our MHK tracking setpoints accordingly
switch (mode) {
case climate::CLIMATE_MODE_COOL:
case climate::CLIMATE_MODE_DRY:
this->mhk_state_.cool_setpoint_ = target_temperature;
break;
case climate::CLIMATE_MODE_HEAT:
this->mhk_state_.heat_setpoint_ = target_temperature;
break;
case climate::CLIMATE_MODE_HEAT_COOL:
if (this->get_traits().get_supports_two_point_target_temperature()) {
this->mhk_state_.cool_setpoint_ = target_temperature_low;
this->mhk_state_.heat_setpoint_ = target_temperature_high;
} else {
// HACK: This is not accurate, but it's good enough for testing.
this->mhk_state_.cool_setpoint_ = target_temperature + 2;
this->mhk_state_.heat_setpoint_ = target_temperature - 2;
}
default:
break;
}
}

// TODO:
Expand All @@ -89,10 +111,10 @@ void MitsubishiUART::control(const climate::ClimateCall &call) {
// Queue the packet to be sent first (so any subsequent update packets come *after* our changes)
hp_bridge_.send_packet(set_request_packet);

// Publish state and any sensor changes (shouldn't be any a a result of this function, but
// Publish state and any sensor changes (shouldn't be any a result of this function, but
// since they lazy-publish, no harm in trying)
do_publish_();
};
}

} // namespace mitsubishi_itp
} // namespace esphome
Loading