From 4b5e60fc2b56c63d98865ad22daaadd756588e46 Mon Sep 17 00:00:00 2001 From: Miika Pekkarinen Date: Sun, 6 Oct 2024 16:32:48 +0300 Subject: [PATCH] Add support for outside air temperature sensor (reported by the outdoor unit). --- components/cn105/Globals.h | 2 ++ components/cn105/climate.py | 21 +++++++++++++++++-- components/cn105/cn105.cpp | 1 - components/cn105/cn105.h | 6 +++++- components/cn105/extraComponents.cpp | 5 +++++ components/cn105/hp_readings.cpp | 21 ++++++++++++++++++- .../cn105/outside_air_temperature_sensor.h | 17 +++++++++++++++ 7 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 components/cn105/outside_air_temperature_sensor.h diff --git a/components/cn105/Globals.h b/components/cn105/Globals.h index 85687aa..4cb8371 100644 --- a/components/cn105/Globals.h +++ b/components/cn105/Globals.h @@ -244,12 +244,14 @@ struct heatpumpTimers { struct heatpumpStatus { float roomTemperature; + float outsideAirTemperature; bool operating; // if true, the heatpump is operating to reach the desired temperature heatpumpTimers timers; int compressorFrequency; bool operator==(const heatpumpStatus& other) const { return roomTemperature == other.roomTemperature && + outsideAirTemperature == other.outsideAirTemperature && operating == other.operating && //timers == other.timers && // Assurez-vous que l'opérateur == est également défini pour heatpumpTimers compressorFrequency == other.compressorFrequency; diff --git a/components/cn105/climate.py b/components/cn105/climate.py index 9646810..3407170 100644 --- a/components/cn105/climate.py +++ b/components/cn105/climate.py @@ -35,6 +35,7 @@ CONF_HORIZONTAL_SWING_SELECT = "horizontal_vane_select" CONF_VERTICAL_SWING_SELECT = "vertical_vane_select" CONF_COMPRESSOR_FREQUENCY_SENSOR = "compressor_frequency_sensor" +CONF_OUTSIDE_AIR_TEMPERATURE_SENSOR = "outside_air_temperature_sensor" CONF_ISEE_SENSOR = "isee_sensor" CONF_STAGE_SENSOR = "stage_sensor" CONF_SUB_MODE_SENSOR = "sub_mode_sensor" @@ -59,6 +60,10 @@ "CompressorFrequencySensor", sensor.Sensor, cg.Component ) +OutsideAirTemperatureSensor = cg.global_ns.class_( + "OutsideAirTemperatureSensor", sensor.Sensor, cg.Component +) + ISeeSensor = cg.global_ns.class_("ISeeSensor", binary_sensor.BinarySensor, cg.Component) StageSensor = cg.global_ns.class_("StageSensor", text_sensor.TextSensor, cg.Component) SubModSensor = cg.global_ns.class_("SubModSensor", text_sensor.TextSensor, cg.Component) @@ -87,10 +92,14 @@ def valid_uart(uart): {cv.GenerateID(CONF_ID): cv.declare_id(VaneOrientationSelect)} ) -SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend( +COMPRESSOR_FREQUENCY_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend( {cv.GenerateID(CONF_ID): cv.declare_id(CompressorFrequencySensor)} ) +OUTSIDE_AIR_TEMPERATURE_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend( + {cv.GenerateID(CONF_ID): cv.declare_id(OutsideAirTemperatureSensor)} +) + ISEE_SENSOR_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( {cv.GenerateID(CONF_ID): cv.declare_id(ISeeSensor)} ) @@ -132,7 +141,8 @@ def valid_uart(uart): cv.Optional(CONF_UPDATE_INTERVAL, default="2s"): cv.All(cv.update_interval), cv.Optional(CONF_HORIZONTAL_SWING_SELECT): SELECT_SCHEMA, cv.Optional(CONF_VERTICAL_SWING_SELECT): SELECT_SCHEMA, - cv.Optional(CONF_COMPRESSOR_FREQUENCY_SENSOR): SENSOR_SCHEMA, + cv.Optional(CONF_COMPRESSOR_FREQUENCY_SENSOR): COMPRESSOR_FREQUENCY_SENSOR_SCHEMA, + cv.Optional(CONF_OUTSIDE_AIR_TEMPERATURE_SENSOR): OUTSIDE_AIR_TEMPERATURE_SENSOR_SCHEMA, cv.Optional(CONF_ISEE_SENSOR): ISEE_SENSOR_SCHEMA, cv.Optional(CONF_STAGE_SENSOR): STAGE_SENSOR_SCHEMA, cv.Optional(CONF_SUB_MODE_SENSOR): SUB_MODE_SENSOR_SCHEMA, @@ -209,6 +219,13 @@ def to_code(config): yield cg.register_component(sensor_, conf) cg.add(var.set_compressor_frequency_sensor(sensor_)) + if CONF_OUTSIDE_AIR_TEMPERATURE_SENSOR in config: + conf = config[CONF_OUTSIDE_AIR_TEMPERATURE_SENSOR] + conf["force_update"] = False + sensor_ = yield sensor.new_sensor(conf) + yield cg.register_component(sensor_, conf) + cg.add(var.set_outside_air_temperature_sensor(sensor_)) + if CONF_ISEE_SENSOR in config: conf = config[CONF_ISEE_SENSOR] bsensor_ = yield binary_sensor.new_binary_sensor(conf) diff --git a/components/cn105/cn105.cpp b/components/cn105/cn105.cpp index 638f5c6..c54ce7d 100644 --- a/components/cn105/cn105.cpp +++ b/components/cn105/cn105.cpp @@ -178,4 +178,3 @@ bool CN105Climate::isHeatpumpConnectionActive() { return (lrTimeMs < MAX_DELAY_RESPONSE_FACTOR * this->update_interval_); } - diff --git a/components/cn105/cn105.h b/components/cn105/cn105.h index 9ba37ea..079c65c 100644 --- a/components/cn105/cn105.h +++ b/components/cn105/cn105.h @@ -4,6 +4,7 @@ #include "van_orientation_select.h" #include "uptime_connection_sensor.h" #include "compressor_frequency_sensor.h" +#include "outside_air_temperature_sensor.h" #include "auto_sub_mode_sensor.h" #include "isee_sensor.h" #include "stage_sensor.h" @@ -33,6 +34,7 @@ class CN105Climate : public climate::Climate, public Component, public uart::UAR void set_vertical_vane_select(VaneOrientationSelect* vertical_vane_select); void set_horizontal_vane_select(VaneOrientationSelect* horizontal_vane_select); void set_compressor_frequency_sensor(esphome::sensor::Sensor* compressor_frequency_sensor); + void set_outside_air_temperature_sensor(esphome::sensor::Sensor* outside_air_temperature_sensor); void set_isee_sensor(esphome::binary_sensor::BinarySensor* iSee_sensor); void set_stage_sensor(esphome::text_sensor::TextSensor* Stage_sensor); void set_sub_mode_sensor(esphome::text_sensor::TextSensor* Sub_mode_sensor); @@ -54,6 +56,8 @@ class CN105Climate : public climate::Climate, public Component, public uart::UAR nullptr; // Select to store manual position of horizontal swing sensor::Sensor* compressor_frequency_sensor_ = nullptr; // Sensor to store compressor frequency + sensor::Sensor* outside_air_temperature_sensor_ = + nullptr; // Outside air temperature // sensor to monitor heatpump connection time uptime::HpUpTimeConnectionSensor* hp_uptime_connection_sensor_ = nullptr; @@ -285,7 +289,7 @@ class CN105Climate : public climate::Climate, public Component, public uart::UAR uint8_t* data; // initialise to all off, then it will update shortly after connect; - heatpumpStatus currentStatus{ 0, false, {TIMER_MODE_MAP[0], 0, 0, 0, 0}, 0 }; + heatpumpStatus currentStatus{ 0, 0, false, {TIMER_MODE_MAP[0], 0, 0, 0, 0}, 0 }; heatpumpFunctions functions; bool tempMode = false; diff --git a/components/cn105/extraComponents.cpp b/components/cn105/extraComponents.cpp index 66fcf61..de23e94 100644 --- a/components/cn105/extraComponents.cpp +++ b/components/cn105/extraComponents.cpp @@ -57,6 +57,11 @@ void CN105Climate::set_compressor_frequency_sensor( this->compressor_frequency_sensor_ = compressor_frequency_sensor; } +void CN105Climate::set_outside_air_temperature_sensor( + sensor::Sensor* outside_air_temperature_sensor) { + this->outside_air_temperature_sensor_ = outside_air_temperature_sensor; +} + void CN105Climate::set_isee_sensor(esphome::binary_sensor::BinarySensor* iSee_sensor) { this->iSee_sensor_ = iSee_sensor; } diff --git a/components/cn105/hp_readings.cpp b/components/cn105/hp_readings.cpp index 5d47a1e..5dfe151 100644 --- a/components/cn105/hp_readings.cpp +++ b/components/cn105/hp_readings.cpp @@ -228,6 +228,18 @@ void CN105Climate::getRoomTemperatureFromResponsePacket() { //ESP_LOGD("Decoder", "[0x03 room temperature]"); //this->last_received_packet_sensor->publish_state("0x62-> 0x03: Data -> Room temperature"); + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // FC 62 01 30 10 03 00 00 0E 00 94 B0 B0 FE 42 00 01 0A 64 00 00 A9 + // RT OT RT SP ?? ?? ?? CT CT + // RT = room temperature (in old format and in new format) + // OT = outside air temperature + // SP = room setpoint temperature? + // CT = increasing counter (unknown function) + + if (data[5] != 0x00) + receivedStatus.outsideAirTemperature = (float)(data[5] - 128) / 2; + else + receivedStatus.outsideAirTemperature = -1; if (data[6] != 0x00) { int temp = data[6]; @@ -236,7 +248,9 @@ void CN105Climate::getRoomTemperatureFromResponsePacket() { } else { receivedStatus.roomTemperature = lookupByteMapValue(ROOM_TEMP_MAP, ROOM_TEMP, 32, data[3]); } + ESP_LOGD("Decoder", "[Room °C: %f]", receivedStatus.roomTemperature); + ESP_LOGD("Decoder", "[OAT °C: %f]", receivedStatus.outsideAirTemperature); // no change with this packet to currentStatus for operating and compressorFrequency receivedStatus.operating = currentStatus.operating; @@ -257,6 +271,7 @@ void CN105Climate::getOperatingAndCompressorFreqFromResponsePacket() { // no change with this packet to roomTemperature receivedStatus.roomTemperature = currentStatus.roomTemperature; + receivedStatus.outsideAirTemperature = currentStatus.outsideAirTemperature; this->statusChanged(receivedStatus); } @@ -406,6 +421,7 @@ void CN105Climate::statusChanged(heatpumpStatus status) { this->currentStatus.operating = status.operating; this->currentStatus.compressorFrequency = status.compressorFrequency; this->currentStatus.roomTemperature = status.roomTemperature; + this->currentStatus.outsideAirTemperature = status.outsideAirTemperature; this->current_temperature = currentStatus.roomTemperature; this->updateAction(); // update action info on HA climate component @@ -414,6 +430,10 @@ void CN105Climate::statusChanged(heatpumpStatus status) { if (this->compressor_frequency_sensor_ != nullptr) { this->compressor_frequency_sensor_->publish_state(currentStatus.compressorFrequency); } + + if (this->outside_air_temperature_sensor_ != nullptr) { + this->outside_air_temperature_sensor_->publish_state(currentStatus.outsideAirTemperature); + } } // else no change } @@ -622,4 +642,3 @@ void CN105Climate::checkPowerAndModeSettings(heatpumpSettings& settings, bool up } } } - diff --git a/components/cn105/outside_air_temperature_sensor.h b/components/cn105/outside_air_temperature_sensor.h new file mode 100644 index 0000000..a253216 --- /dev/null +++ b/components/cn105/outside_air_temperature_sensor.h @@ -0,0 +1,17 @@ +#pragma once + +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" + + +namespace esphome { + + class OutsideAirTemperatureSensor : public sensor::Sensor, public Component { + public: + OutsideAirTemperatureSensor() { + this->set_unit_of_measurement("°C"); + this->set_accuracy_decimals(1); + } + }; + +}