From 9814c5f76fd33c13b87217902cbe62075253c82c Mon Sep 17 00:00:00 2001 From: dkarv Date: Wed, 7 Aug 2024 20:02:40 +0200 Subject: [PATCH 1/4] implement u32 values --- esphome/components/toptronic/toptronic.cpp | 59 +++++++++++++++++----- esphome/components/toptronic/toptronic.h | 3 ++ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/esphome/components/toptronic/toptronic.cpp b/esphome/components/toptronic/toptronic.cpp index d3b6db1..97a878c 100644 --- a/esphome/components/toptronic/toptronic.cpp +++ b/esphome/components/toptronic/toptronic.cpp @@ -306,19 +306,57 @@ void log_response_frame(std::vector data, uint32_t can_id, std::string } void TopTronic::parse_frame(std::vector data, uint32_t can_id, bool remote_transmission_request) { + uint8_t msg_id = can_id >> 24; + uint8_t device_type = (can_id >> 8) & 0xFF; + uint8_t device_id = can_id & 0xFF; + + if (msg_id == 0x1f) { + // Start of a message + uint8_t msg_len = data[0] >> 3; + if (msg_len == 0) { + // Full message, remove size + interpret_message(std::vector(data.begin() + 1, data.end()), can_id, remote_transmission_request); + } else { + // We expect further messages + u_int8_t msg_header = data[1]; + ESP_LOGI(TAG, "Start of message with id: %d with length %d", msg_header, msg_len); + pending_messages_[msg_header] = std::make_pair(std::vector(data.begin() + 2, data.end()), msg_len -1); + } + } else { + u_int8_t msg_header = data[0]; + auto it = pending_messages_.find(msg_header); + if (it != pending_messages_.end()) { + auto pending_msg = it->second; + auto msg_len = pending_msg.second - 1; + ESP_LOGI(TAG, "Part of message with id: %d with remaining length %d", msg_header, msg_len); + pending_msg.first.insert(pending_msg.first.end(), data.begin() + 1, data.end()); + if (msg_len == 0) { + pending_messages_.erase(msg_header); + // Delete the last two bytes (CRC?) + auto real_msg = std::vector(pending_msg.first.begin(), pending_msg.first.end() - 2); + interpret_message(real_msg, can_id, remote_transmission_request); + } else { + pending_messages_[msg_header] = std::make_pair(pending_msg.first, msg_len); + } + } + } +} + +void TopTronic::interpret_message(std::vector data, uint32_t can_id, bool remote_transmission_request) { // check if operation is of type RESPONSE - if (data[1] == GET_REQ) { - // ESP_LOGI(TAG, "[GET] Can-ID: 0x%08X, Data: 0x%s", can_id, hex_str(&data[0], data.size()).c_str()); + if (data[0] == GET_REQ) { + ESP_LOGI(TAG, "[GET] Can-ID: 0x%08X, Data: 0x%s", can_id, hex_str(&data[0], data.size()).c_str()); return; } - if (data[1] == SET_REQ) { + if (data[0] == SET_REQ) { ESP_LOGI(TAG, "[SET] Can-ID: 0x%08X, Data: 0x%s", can_id, hex_str(&data[0], data.size()).c_str()); return; } - if (data[1] != RESPONSE) { + if (data[0] != RESPONSE) { + ESP_LOGI(TAG, "[UNK] Can-ID: 0x%08X, Data: 0x%s", can_id, hex_str(&data[0], data.size()).c_str()); return; } @@ -330,9 +368,9 @@ void TopTronic::parse_frame(std::vector data, uint32_t can_id, bool rem TopTronicDevice *device = devices_[device_id]; // check if sensor exists for the received value - uint32_t datapoint = data[5] + (data[4] << 8); - uint32_t id = data[2] // function_group - + (data[3] << 8) // function_number + uint32_t datapoint = data[4] + (data[3] << 8); + uint32_t id = data[1] // function_group + + (data[2] << 8) // function_number + (datapoint << 16); if (device->sensors.count(id) <= 0) { @@ -342,18 +380,15 @@ void TopTronic::parse_frame(std::vector data, uint32_t can_id, bool rem if (sensorBase->type() == SENSOR) { TopTronicSensor *sensor = (TopTronicSensor*)sensorBase; - float value = sensor->parse_value(std::vector(data.begin() + 6, data.end())); + float value = sensor->parse_value(std::vector(data.begin() + 5, data.end())); sensor->publish_state(value); log_response_frame(data, can_id, sensor->get_name()); } else if (sensorBase->type() == TEXTSENSOR) { TopTronicTextSensor *sensor = (TopTronicTextSensor*)sensorBase; - std::string value = sensor->parse_value(std::vector(data.begin() + 6, data.end())); + std::string value = sensor->parse_value(std::vector(data.begin() + 5, data.end())); sensor->publish_state(value); log_response_frame(data, can_id, sensor->get_name()); } - - - } } // namespace toptronic diff --git a/esphome/components/toptronic/toptronic.h b/esphome/components/toptronic/toptronic.h index 89298cd..d2e10df 100644 --- a/esphome/components/toptronic/toptronic.h +++ b/esphome/components/toptronic/toptronic.h @@ -143,9 +143,12 @@ class TopTronic : public Component { TopTronicDevice* get_or_create_device(uint32_t can_id); void link_inputs(); TopTronicBase* get_sensor(uint32_t device_id, uint32_t sensor_id); + void interpret_message(std::vector data, uint32_t can_id, bool remote_transmission_request); canbus::Canbus *canbus_; std::map devices_; + // msg_header -> (data, number of pending messages) + std::map, uint8_t>> pending_messages_; uint16_t device_type_; uint8_t device_addr_; From 2e921f07175e917c3b7aee5ab6f37c3ae31fe038 Mon Sep 17 00:00:00 2001 From: dkarv Date: Wed, 7 Aug 2024 21:25:10 +0200 Subject: [PATCH 2/4] remove _high or _low from entity name --- esphome/.gitignore | 1 + .../hoval_data_processing/generate_presets.py | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/esphome/.gitignore b/esphome/.gitignore index 3caea8b..cabc338 100644 --- a/esphome/.gitignore +++ b/esphome/.gitignore @@ -5,6 +5,7 @@ secrets.yaml *.pyc .vscode +.venv notes.md can.log \ No newline at end of file diff --git a/esphome/hoval_data_processing/generate_presets.py b/esphome/hoval_data_processing/generate_presets.py index 8f39fa6..06441c5 100644 --- a/esphome/hoval_data_processing/generate_presets.py +++ b/esphome/hoval_data_processing/generate_presets.py @@ -5,6 +5,7 @@ import openpyxl from openpyxl import Workbook from typing import Callable, Optional +import re PatchFunc = Callable[[list[Datapoint], str], None] @@ -65,6 +66,7 @@ def wez_before_dump(datapoints: list[Datapoint], locale: str): for dp in datapoints: if dp.row in rows: dp.name = f'{dp.name} ({dp.function_number+1})' + u32_before_dump(datapoints, locale) def bd_before_dump(datapoints: list[Datapoint], locale: str): translations = { @@ -82,6 +84,12 @@ def bd_before_dump(datapoints: list[Datapoint], locale: str): } } _translate(datapoints, locale, translations) + u32_before_dump(datapoints, locale) + +def u32_before_dump(datapoints: list[Datapoint], locale: str): + for dp in datapoints: + if dp.type_name in ["U32", "S32"]: + dp.name = re.sub(r'(_low|_high)$', "", dp.name) if __name__ == "__main__": presets = [ @@ -97,6 +105,14 @@ def bd_before_dump(datapoints: list[Datapoint], locale: str): 1400, # Hot water setpoint 1401, # hot water temp. 1437, # WEZ output + 24775, # Electrical power WEZ + 24776, # Heating power WEZ + 24778, # Electrical energy WEZ MWh + 26631, # Total energy efficiency H-Gen + 26649, # Heat quantity heating + 26653, # Heat quantity DHW + 26654, # Coefficient of Performance + 26699, # Current sunlight expos. (global rad.) ]), before_dump=wez_before_dump), Preset('HV', Filter(rows=[ 22705, # Outside air temp. @@ -112,7 +128,7 @@ def bd_before_dump(datapoints: list[Datapoint], locale: str): 22696, # Normal ventilation modulation 22697, # Eco ventilation modulation 22699, # Humidity set value - ]), hv_before_translate), + ]), hv_before_translate, u32_before_dump), Preset('BM', [ Datapoint( row=0, From a38f4205188d70185894978c9971c05bd431c86a Mon Sep 17 00:00:00 2001 From: dkarv Date: Wed, 7 Aug 2024 21:27:13 +0200 Subject: [PATCH 3/4] Revert "remove _high or _low from entity name" This reverts commit 2e921f07175e917c3b7aee5ab6f37c3ae31fe038. --- esphome/.gitignore | 1 - .../hoval_data_processing/generate_presets.py | 18 +----------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/esphome/.gitignore b/esphome/.gitignore index cabc338..3caea8b 100644 --- a/esphome/.gitignore +++ b/esphome/.gitignore @@ -5,7 +5,6 @@ secrets.yaml *.pyc .vscode -.venv notes.md can.log \ No newline at end of file diff --git a/esphome/hoval_data_processing/generate_presets.py b/esphome/hoval_data_processing/generate_presets.py index 06441c5..8f39fa6 100644 --- a/esphome/hoval_data_processing/generate_presets.py +++ b/esphome/hoval_data_processing/generate_presets.py @@ -5,7 +5,6 @@ import openpyxl from openpyxl import Workbook from typing import Callable, Optional -import re PatchFunc = Callable[[list[Datapoint], str], None] @@ -66,7 +65,6 @@ def wez_before_dump(datapoints: list[Datapoint], locale: str): for dp in datapoints: if dp.row in rows: dp.name = f'{dp.name} ({dp.function_number+1})' - u32_before_dump(datapoints, locale) def bd_before_dump(datapoints: list[Datapoint], locale: str): translations = { @@ -84,12 +82,6 @@ def bd_before_dump(datapoints: list[Datapoint], locale: str): } } _translate(datapoints, locale, translations) - u32_before_dump(datapoints, locale) - -def u32_before_dump(datapoints: list[Datapoint], locale: str): - for dp in datapoints: - if dp.type_name in ["U32", "S32"]: - dp.name = re.sub(r'(_low|_high)$', "", dp.name) if __name__ == "__main__": presets = [ @@ -105,14 +97,6 @@ def u32_before_dump(datapoints: list[Datapoint], locale: str): 1400, # Hot water setpoint 1401, # hot water temp. 1437, # WEZ output - 24775, # Electrical power WEZ - 24776, # Heating power WEZ - 24778, # Electrical energy WEZ MWh - 26631, # Total energy efficiency H-Gen - 26649, # Heat quantity heating - 26653, # Heat quantity DHW - 26654, # Coefficient of Performance - 26699, # Current sunlight expos. (global rad.) ]), before_dump=wez_before_dump), Preset('HV', Filter(rows=[ 22705, # Outside air temp. @@ -128,7 +112,7 @@ def u32_before_dump(datapoints: list[Datapoint], locale: str): 22696, # Normal ventilation modulation 22697, # Eco ventilation modulation 22699, # Humidity set value - ]), hv_before_translate, u32_before_dump), + ]), hv_before_translate), Preset('BM', [ Datapoint( row=0, From 4220fc2c6840a44e37bd933d14d011a8a14e62af Mon Sep 17 00:00:00 2001 From: dkarv Date: Wed, 7 Aug 2024 21:32:00 +0200 Subject: [PATCH 4/4] remove _low or _high prefix from entity name --- esphome/.gitignore | 1 + esphome/hoval_data_processing/generate_presets.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/esphome/.gitignore b/esphome/.gitignore index 3caea8b..cabc338 100644 --- a/esphome/.gitignore +++ b/esphome/.gitignore @@ -5,6 +5,7 @@ secrets.yaml *.pyc .vscode +.venv notes.md can.log \ No newline at end of file diff --git a/esphome/hoval_data_processing/generate_presets.py b/esphome/hoval_data_processing/generate_presets.py index 8f39fa6..eb137d7 100644 --- a/esphome/hoval_data_processing/generate_presets.py +++ b/esphome/hoval_data_processing/generate_presets.py @@ -5,6 +5,7 @@ import openpyxl from openpyxl import Workbook from typing import Callable, Optional +import re PatchFunc = Callable[[list[Datapoint], str], None] @@ -26,6 +27,10 @@ def generate(self, wb: Workbook, out_dir: pathlib.Path): if self.before_dump: self.before_dump(datapoints, locale) + + for dp in datapoints: + if dp.type_name in ["U32", "S32"]: + dp.name = re.sub(r'(_low|_high)$', "", dp.name) os.makedirs(out_dir.joinpath(self.id), exist_ok=True)