From aaf95e79d4c40837490a642027a10bd55a49dedb Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 25 Feb 2023 19:34:13 +0100 Subject: [PATCH] testing support for Vario Heater --- components/truma_inetbox/TrumaiNetBoxApp.cpp | 50 +++++++++++++++---- components/truma_inetbox/TrumaiNetBoxApp.h | 25 ++++++++-- .../TrumaiNetBoxApp_automation.cpp | 48 +++++++++++++----- components/truma_inetbox/__init__.py | 2 + 4 files changed, 100 insertions(+), 25 deletions(-) diff --git a/components/truma_inetbox/TrumaiNetBoxApp.cpp b/components/truma_inetbox/TrumaiNetBoxApp.cpp index 8ce3197..67100e3 100644 --- a/components/truma_inetbox/TrumaiNetBoxApp.cpp +++ b/components/truma_inetbox/TrumaiNetBoxApp.cpp @@ -195,11 +195,11 @@ bool TrumaiNetBoxApp::lin_read_field_by_identifier_(u_int8_t identifier, std::ar (*response)[1] = lin_identifier[1]; (*response)[2] = lin_identifier[2]; (*response)[3] = lin_identifier[3]; - (*response)[4] = 0x01; // Hardware revision + (*response)[4] = 0x01; // Variant return true; } else if (identifier == 0x20 /* Product details to display in CP plus */) { auto lin_identifier = this->lin_identifier(); - // Only the first three parts are used. + // Only the first three parts are displayed. (*response)[0] = lin_identifier[0]; (*response)[1] = lin_identifier[1]; (*response)[2] = lin_identifier[2]; @@ -322,7 +322,7 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message this->update_status_timer_stale_ = false; - ESP_LOGV(TAG, "StatusFrameTimer target_temp_room: %f target_temp_water: %f %u:%u -> %u:%u %s", + ESP_LOGD(TAG, "StatusFrameTimer target_temp_room: %f target_temp_water: %f %u:%u -> %u:%u %s", temp_code_to_decimal(this->status_timer_.timer_target_temp_room), temp_code_to_decimal(this->status_timer_.timer_target_temp_water), this->status_timer_.timer_start_hours, this->status_timer_.timer_start_minutes, this->status_timer_.timer_stop_hours, @@ -341,7 +341,7 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message } else { ESP_LOGI(TAG, "StatusFrameResponseAck"); } - ESP_LOGV(TAG, "StatusFrameResponseAck %02X %s %02X", statusFrame->inner.genericHeader.command_counter, + ESP_LOGD(TAG, "StatusFrameResponseAck %02X %s %02X", statusFrame->inner.genericHeader.command_counter, data.error_code == ResponseAckResult::RESPONSE_ACK_RESULT_OKAY ? " OKAY " : " FAILED ", (u_int8_t) data.error_code); @@ -362,7 +362,7 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message this->status_clock_valid_ = true; this->status_clock_updated_ = true; - ESP_LOGV(TAG, "StatusFrameClock %02d:%02d:%02d", this->status_clock_.clock_hour, this->status_clock_.clock_minute, + ESP_LOGD(TAG, "StatusFrameClock %02d:%02d:%02d", this->status_clock_.clock_hour, this->status_clock_.clock_minute, this->status_clock_.clock_second); return response; @@ -377,7 +377,7 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message this->status_config_valid_ = true; this->status_config_updated_ = true; - ESP_LOGV(TAG, "StatusFrameConfig Offset: %d", offset_code_to_decimal(this->status_config_.temp_offset)); + ESP_LOGD(TAG, "StatusFrameConfig Offset: %d", offset_code_to_decimal(this->status_config_.temp_offset)); return response; } else if (header->message_type == STATUS_FRAME_DEVICES && header->message_length == sizeof(StatusFrameDevice)) { @@ -385,15 +385,47 @@ const u_int8_t *TrumaiNetBoxApp::lin_multiframe_recieved(const u_int8_t *message // This message is special. I recieve one response per registered (at CP plus) device. // Example: // SID<---------PREAMBLE---------->|<---MSG_HEAD---->| + // Combi4 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0C.0B.00.79.02.00.01.00.50.00.00.04.03.02.AD.10 - C4.03.02 0050.00 // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0C.0B.00.27.02.01.01.00.40.03.22.02.00.01.00.00 - H2.00.01 0340.22 + // VarioHeat Comfort w/o E-Kit + // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0C.0B.00.C2.02.00.01.00.51.00.00.05.01.00.66.10 - P5.01.00 0051.00 + // BB.00.1F.00.1E.00.00.22.FF.FF.FF.54.01.0C.0B.00.64.02.01.01.00.20.06.02.03.00.00.00.00 - H3.00.00 0620.02 + auto device = statusFrame->inner.device; this->init_recieved_ = micros(); - ESP_LOGV(TAG, "StatusFrameDevice %d/%d - %d.%02d.%02d %04X.%02X", device.device_id + 1, device.device_count, - device.software_revision[0], device.software_revision[1], device.software_revision[2], - device.hardware_revision_major, device.hardware_revision_minor); + ESP_LOGD(TAG, "StatusFrameDevice %d/%d - %d.%02d.%02d %04X.%02X (%02X %02X)", device.device_id + 1, + device.device_count, device.software_revision[0], device.software_revision[1], device.software_revision[2], + device.hardware_revision_major, device.hardware_revision_minor, device.unkown_2, device.unkown_3); + + { + bool found_unkown_value = false; + if (device.unkown_0 != 0x01 || device.unkown_1 != 0x00) + found_unkown_value = true; + if (device.software_revision[0] != TRUMA_DEVICE::HEATER_COMBI && + device.software_revision[0] != TRUMA_DEVICE::HEATER_VARIO && + device.software_revision[0] != TRUMA_DEVICE::CPPLUS_COMBI && + device.software_revision[0] != TRUMA_DEVICE::CPPLUS_VARIO) + found_unkown_value = true; + if (device.unkown_2 != 0xAD && device.unkown_2 != 0x66 && device.unkown_2 != 0x00) + found_unkown_value = true; + if (device.unkown_3 != 0x10 && device.unkown_3 != 0x00) + found_unkown_value = true; + + if (found_unkown_value) + ESP_LOGW(TAG, "Unkown information in StatusFrameDevice found. Please report."); + } + + // Assumption device id one is always the heater. + if (device.device_id == 1) { + if (device.software_revision[0] == TRUMA_DEVICE::HEATER_COMBI) { + this->heater_device_ = TRUMA_DEVICE::HEATER_COMBI; + } else if (device.software_revision[0] == TRUMA_DEVICE::HEATER_VARIO) { + this->heater_device_ = TRUMA_DEVICE::HEATER_VARIO; + } + } return response; } else { diff --git a/components/truma_inetbox/TrumaiNetBoxApp.h b/components/truma_inetbox/TrumaiNetBoxApp.h index 29f034a..7fad866 100644 --- a/components/truma_inetbox/TrumaiNetBoxApp.h +++ b/components/truma_inetbox/TrumaiNetBoxApp.h @@ -45,8 +45,15 @@ namespace truma_inetbox { enum class HeatingMode : u_int16_t { HEATING_MODE_OFF = 0x0, + // COMBI HEATING_MODE_ECO = 0x1, + // Vario Heat + HEATING_MODE_VARIO_HEAT_NIGHT = 0x2, + // Vario Heat + HEATING_MODE_VARIO_HEAT_AUTO = 0x3, + // COMBI HEATING_MODE_HIGH = 0xA, + // COMBI, Vario Heat HEATING_MODE_BOOST = 0xB, // Feedback Invalid message only with following `heating_mode`. Others are ignored no feedback. @@ -297,6 +304,14 @@ struct StatusFrameConfig { // NOLINT(altera-struct-pack-align) u_int8_t unkown_8; } __attribute__((packed)); +enum class TRUMA_DEVICE : u_int8_t { + UNKOWN = 0x00, + HEATER_COMBI = 0x02, + HEATER_VARIO = 0x03, + CPPLUS_COMBI = 0x04, + CPPLUS_VARIO = 0x05, +}; + // Length 12 (0x0C) struct StatusFrameDevice { // NOLINT(altera-struct-pack-align) u_int8_t device_count; @@ -308,12 +323,13 @@ struct StatusFrameDevice { // NOLINT(altera-struct-pack-align) u_int16_t hardware_revision_major; u_int8_t hardware_revision_minor; // `software_revision[0].software_revision[1].software_revision[2]` + // software_revision[0] -> TRUMA_DEVICE u_int8_t software_revision[3]; - // 0xAD on CPplus - // 0x00 on Combi4 + // 0xAD on CPplus with Combi4 or 0x66 on CPplus with Vario Heat Comfort ohne E + // 0x00 on Combi4, Vario Heat u_int8_t unkown_2; // 0x10 on CPplus - // 0x00 on Combi4 + // 0x00 on Combi4, Vario Heat u_int8_t unkown_3; } __attribute__((packed)); @@ -417,6 +433,9 @@ class TrumaiNetBoxApp : public LinBusProtocol { uint32_t init_recieved_ = 0; u_int8_t message_counter = 1; + // Truma heater conected to CP Plus. + TRUMA_DEVICE heater_device_ = TRUMA_DEVICE::HEATER_COMBI; + std::vector listeners_heater_; CallbackManager state_heater_callback_{}; diff --git a/components/truma_inetbox/TrumaiNetBoxApp_automation.cpp b/components/truma_inetbox/TrumaiNetBoxApp_automation.cpp index ebce42a..8ddade1 100644 --- a/components/truma_inetbox/TrumaiNetBoxApp_automation.cpp +++ b/components/truma_inetbox/TrumaiNetBoxApp_automation.cpp @@ -22,12 +22,23 @@ bool TrumaiNetBoxApp::action_heater_room(u_int8_t temperature, HeatingMode mode) if (heater->target_temp_room == TargetTemp::TARGET_TEMP_OFF) { heater->heating_mode = HeatingMode::HEATING_MODE_OFF; } else { - // If parameter `mode` contains a valid Heating mode use it or else use `ECO`. - if (mode == HeatingMode::HEATING_MODE_ECO || mode == HeatingMode::HEATING_MODE_HIGH || - mode == HeatingMode::HEATING_MODE_BOOST) { - heater->heating_mode = mode; - } else if (heater->heating_mode == HeatingMode::HEATING_MODE_OFF) { - heater->heating_mode = HeatingMode::HEATING_MODE_ECO; + if (this->heater_device_ == TRUMA_DEVICE::HEATER_VARIO) { + // If parameter `mode` contains a valid Heating mode use it or else use `AUTO`. + if (mode == HeatingMode::HEATING_MODE_VARIO_HEAT_NIGHT || mode == HeatingMode::HEATING_MODE_VARIO_HEAT_AUTO || + mode == HeatingMode::HEATING_MODE_BOOST) { + heater->heating_mode = mode; + } else if (heater->heating_mode == HeatingMode::HEATING_MODE_OFF) { + heater->heating_mode = HeatingMode::HEATING_MODE_VARIO_HEAT_AUTO; + } + } else { + // HEATER_COMBI + // If parameter `mode` contains a valid Heating mode use it or else use `ECO`. + if (mode == HeatingMode::HEATING_MODE_ECO || mode == HeatingMode::HEATING_MODE_HIGH || + mode == HeatingMode::HEATING_MODE_BOOST) { + heater->heating_mode = mode; + } else if (heater->heating_mode == HeatingMode::HEATING_MODE_OFF) { + heater->heating_mode = HeatingMode::HEATING_MODE_ECO; + } } } if (heater->energy_mix_a == EnergyMix::ENERGY_MIX_NONE) { @@ -178,12 +189,23 @@ bool TrumaiNetBoxApp::action_timer_activate(u_int16_t start, u_int16_t stop, u_i if (timer->timer_target_temp_room == TargetTemp::TARGET_TEMP_OFF) { timer->timer_heating_mode = HeatingMode::HEATING_MODE_OFF; } else { - // If parameter `mode` contains a valid Heating mode use it or else use `ECO`. - if (mode == HeatingMode::HEATING_MODE_ECO || mode == HeatingMode::HEATING_MODE_HIGH || - mode == HeatingMode::HEATING_MODE_BOOST) { - timer->timer_heating_mode = mode; - } else if (timer->timer_heating_mode == HeatingMode::HEATING_MODE_OFF) { - timer->timer_heating_mode = HeatingMode::HEATING_MODE_ECO; + if (this->heater_device_ == TRUMA_DEVICE::HEATER_VARIO) { + // If parameter `mode` contains a valid Heating mode use it or else use `AUTO`. + if (mode == HeatingMode::HEATING_MODE_VARIO_HEAT_NIGHT || mode == HeatingMode::HEATING_MODE_VARIO_HEAT_AUTO || + mode == HeatingMode::HEATING_MODE_BOOST) { + timer->timer_heating_mode = mode; + } else if (timer->timer_heating_mode == HeatingMode::HEATING_MODE_OFF) { + timer->timer_heating_mode = HeatingMode::HEATING_MODE_VARIO_HEAT_AUTO; + } + } else { + // HEATER_COMBI + // If parameter `mode` contains a valid Heating mode use it or else use `ECO`. + if (mode == HeatingMode::HEATING_MODE_ECO || mode == HeatingMode::HEATING_MODE_HIGH || + mode == HeatingMode::HEATING_MODE_BOOST) { + timer->timer_heating_mode = mode; + } else if (timer->timer_heating_mode == HeatingMode::HEATING_MODE_OFF) { + timer->timer_heating_mode = HeatingMode::HEATING_MODE_ECO; + } } } @@ -242,7 +264,7 @@ bool TrumaiNetBoxApp::action_write_time() { this->update_clock_submit(); return true; } -#endif // USE_TIME +#endif // USE_TIME } // namespace truma_inetbox } // namespace esphome \ No newline at end of file diff --git a/components/truma_inetbox/__init__.py b/components/truma_inetbox/__init__.py index 2a5e556..46ca6ee 100644 --- a/components/truma_inetbox/__init__.py +++ b/components/truma_inetbox/__init__.py @@ -327,6 +327,8 @@ HeatingMode_dummy_ns = truma_inetbox_ns.namespace("HeatingMode") CONF_SUPPORTED_HEATING_MODE = { "OFF": HeatingMode_dummy_ns.HEATING_MODE_OFF, "ECO": HeatingMode_dummy_ns.HEATING_MODE_ECO, + "NIGHT": HeatingMode_dummy_ns.HEATING_MODE_VARIO_HEAT_NIGHT, + "AUTO": HeatingMode_dummy_ns.HEATING_MODE_VARIO_HEAT_AUTO, "HIGH": HeatingMode_dummy_ns.HEATING_MODE_HIGH, "BOOST": HeatingMode_dummy_ns.HEATING_MODE_BOOST, }