diff --git a/components/mitsubishi_uart/__init__.py b/components/mitsubishi_uart/__init__.py index f90f1aa..97521df 100644 --- a/components/mitsubishi_uart/__init__.py +++ b/components/mitsubishi_uart/__init__.py @@ -1,6 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import climate, uart, sensor, select, switch +from esphome.components import climate, uart, sensor, binary_sensor, select, switch from esphome.core import CORE from esphome.const import ( CONF_ID, @@ -10,22 +10,23 @@ CONF_SUPPORTED_FAN_MODES, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_FREQUENCY, + DEVICE_CLASS_SPEED, ENTITY_CATEGORY_CONFIG, + ENTITY_CATEGORY_DIAGNOSTIC, STATE_CLASS_MEASUREMENT, UNIT_CELSIUS, UNIT_HERTZ, ) from esphome.core import coroutine -AUTO_LOAD = ["climate", "select", "sensor", "switch"] -DEPENDENCIES = ["uart", "climate", "sensor", "select", "switch"] +AUTO_LOAD = ["climate", "select", "sensor", "binary_sensor", "switch"] +DEPENDENCIES = ["uart", "climate", "sensor", "binary_sensor", "select", "switch"] CONF_HP_UART = "heatpump_uart" CONF_TS_UART = "thermostat_uart" CONF_SENSORS = "sensors" CONF_SENSORS_THERMOSTAT_TEMP = "thermostat_temperature" -CONF_SENSORS_COMPRESSOR_FREQUENCY = "compressor_frequency" CONF_SELECTS = "selects" CONF_TEMPERATURE_SOURCE_SELECT = "temperature_source_select" # This is to create a Select object for selecting a source @@ -76,6 +77,7 @@ icon="mdi:upload-network") }) +# TODO Storing the registration function here seems weird, but I can't figure out how to determine schema type later SENSORS = { CONF_SENSORS_THERMOSTAT_TEMP: ( "Thermostat Temperature", @@ -84,22 +86,50 @@ device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, accuracy_decimals=1, - ) + ), + sensor.register_sensor ), - CONF_SENSORS_COMPRESSOR_FREQUENCY: ( + "compressor_frequency": ( "Compressor Frequency", sensor.sensor_schema( unit_of_measurement=UNIT_HERTZ, device_class=DEVICE_CLASS_FREQUENCY, state_class=STATE_CLASS_MEASUREMENT, - #disabled_by_default=True # This throws an 'unexpected keyword argument' error - ) - ) + ), + sensor.register_sensor + ), + "actual_fan": ( + "Actual Fan Speed", + sensor.sensor_schema( + device_class=DEVICE_CLASS_SPEED, + ), + sensor.register_sensor + ), + "service_filter": ( + "Service Filter", + binary_sensor.binary_sensor_schema(), + binary_sensor.register_binary_sensor + ), + "defrost": ( + "Defrost", + binary_sensor.binary_sensor_schema(), + binary_sensor.register_binary_sensor + ), + "hot_adjust": ( + "Hot Adjust", + binary_sensor.binary_sensor_schema(), + binary_sensor.register_binary_sensor + ), + "standby": ( + "Standby", + binary_sensor.binary_sensor_schema(), + binary_sensor.register_binary_sensor + ), } SENSORS_SCHEMA = cv.All({ cv.Optional(sensor_designator, default={"name": f"{sensor_name}", "disabled_by_default":"true"}): sensor_schema - for sensor_designator, (sensor_name, sensor_schema) in SENSORS.items() + for sensor_designator, (sensor_name, sensor_schema, registration_function) in SENSORS.items() }) SELECTS = { @@ -175,14 +205,16 @@ async def to_code(config): # Sensors - for sensor_designator in SENSORS: + for sensor_designator, (sensor_name, sensor_schema, registration_function) in SENSORS.items(): # Only add the thermostat temp if we have a TS_UART if (sensor_designator == CONF_SENSORS_THERMOSTAT_TEMP) and (CONF_TS_UART not in config): continue sensor_conf = config[CONF_SENSORS][sensor_designator] sensor_component = cg.new_Pvariable(sensor_conf[CONF_ID]) - await sensor.register_sensor(sensor_component, sensor_conf) + + await registration_function(sensor_component, sensor_conf) + cg.add(getattr(muart_component, f"set_{sensor_designator}_sensor")(sensor_component)) ### Selects diff --git a/components/mitsubishi_uart/mitsubishi_uart-packetprocessing.cpp b/components/mitsubishi_uart/mitsubishi_uart-packetprocessing.cpp index 4aecf4d..4abaf5a 100644 --- a/components/mitsubishi_uart/mitsubishi_uart-packetprocessing.cpp +++ b/components/mitsubishi_uart/mitsubishi_uart-packetprocessing.cpp @@ -253,7 +253,38 @@ void MitsubishiUART::processPacket(const StatusGetResponsePacket &packet) { void MitsubishiUART::processPacket(const StandbyGetResponsePacket &packet) { ESP_LOGV(TAG, "Processing %s", packet.to_string().c_str()); routePacket(packet); - // TODO: This packet may contain "loop status" and "stage" information, but want to confirm what it is before using it + + if (service_filter_sensor) { + const bool old_service_filter = service_filter_sensor->state; + service_filter_sensor->state = packet.serviceFilter(); + publishOnUpdate |= (old_service_filter != service_filter_sensor->state); + } + + if (defrost_sensor) { + const bool old_defrost = defrost_sensor->state; + defrost_sensor->state = packet.inDefrost(); + publishOnUpdate |= (old_defrost != defrost_sensor->state); + } + + if (hot_adjust_sensor) { + const bool old_hot_adjust = hot_adjust_sensor->state; + hot_adjust_sensor->state = packet.inHotAdjust(); + publishOnUpdate |= (old_hot_adjust != hot_adjust_sensor->state); + } + + if (standby_sensor) { + const bool old_standby = standby_sensor->state; + standby_sensor->state = packet.inStandby(); + publishOnUpdate |= (old_standby != standby_sensor->state); + } + + if (actual_fan_sensor) { + const uint8_t old_actual_fan = actual_fan_sensor->raw_state; + actual_fan_sensor->raw_state = packet.getActualFanSpeed(); + publishOnUpdate |= (old_actual_fan != actual_fan_sensor->raw_state); + } + + //TODO: Not sure what AutoMode does yet }; void MitsubishiUART::processPacket(const ErrorStateGetResponsePacket &packet) { ESP_LOGV(TAG, "Processing %s", packet.to_string().c_str()); diff --git a/components/mitsubishi_uart/mitsubishi_uart.cpp b/components/mitsubishi_uart/mitsubishi_uart.cpp index 238c342..33ac672 100644 --- a/components/mitsubishi_uart/mitsubishi_uart.cpp +++ b/components/mitsubishi_uart/mitsubishi_uart.cpp @@ -153,6 +153,16 @@ void MitsubishiUART::doPublish() { ESP_LOGI(TAG, "Compressor frequency differs, do publish"); compressor_frequency_sensor->publish_state(compressor_frequency_sensor->raw_state); } + if (actual_fan_sensor && (actual_fan_sensor->raw_state != actual_fan_sensor->state)) { + ESP_LOGI(TAG, "Actual fan speed differs, do publish"); + actual_fan_sensor->publish_state(actual_fan_sensor->raw_state); + } + + // Binary sensors automatically dedup publishes (I think) and so will only actually publish on change + service_filter_sensor->publish_state(service_filter_sensor->state); + defrost_sensor->publish_state(defrost_sensor->state); + hot_adjust_sensor->publish_state(hot_adjust_sensor->state); + standby_sensor->publish_state(standby_sensor->state); } bool MitsubishiUART::select_temperature_source(const std::string &state) { diff --git a/components/mitsubishi_uart/mitsubishi_uart.h b/components/mitsubishi_uart/mitsubishi_uart.h index 05d4889..e6addd5 100644 --- a/components/mitsubishi_uart/mitsubishi_uart.h +++ b/components/mitsubishi_uart/mitsubishi_uart.h @@ -64,6 +64,11 @@ class MitsubishiUART : public PollingComponent, public climate::Climate, public // Sensor setters void set_thermostat_temperature_sensor(sensor::Sensor *sensor) {thermostat_temperature_sensor = sensor;}; void set_compressor_frequency_sensor(sensor::Sensor *sensor) {compressor_frequency_sensor = sensor;}; + void set_actual_fan_sensor(sensor::Sensor *sensor) {actual_fan_sensor = sensor;}; + void set_service_filter_sensor(binary_sensor::BinarySensor *sensor) {service_filter_sensor = sensor;}; + void set_defrost_sensor(binary_sensor::BinarySensor *sensor) {defrost_sensor = sensor;}; + void set_hot_adjust_sensor(binary_sensor::BinarySensor *sensor) {hot_adjust_sensor = sensor;}; + void set_standby_sensor(binary_sensor::BinarySensor *sensor) {standby_sensor = sensor;}; // Select setters void set_temperature_source_select(select::Select *select) {temperature_source_select = select;}; @@ -140,6 +145,11 @@ class MitsubishiUART : public PollingComponent, public climate::Climate, public // Internal sensors sensor::Sensor *thermostat_temperature_sensor = nullptr; sensor::Sensor *compressor_frequency_sensor = nullptr; + sensor::Sensor *actual_fan_sensor = nullptr; + binary_sensor::BinarySensor *service_filter_sensor = nullptr; + binary_sensor::BinarySensor *defrost_sensor = nullptr; + binary_sensor::BinarySensor *hot_adjust_sensor = nullptr; + binary_sensor::BinarySensor *standby_sensor = nullptr; // Selects select::Select *temperature_source_select;