Skip to content

Commit

Permalink
Merge pull request #17 from dkarv/implement-u32
Browse files Browse the repository at this point in the history
Ok tested. 
Needs some refine on generate presets and xls parser,  but works.
I merge and update the needed later. 
Many thanks !
  • Loading branch information
nliaudat authored Aug 8, 2024
2 parents 3a0b710 + 4220fc2 commit 1ab146a
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 12 deletions.
1 change: 1 addition & 0 deletions esphome/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
secrets.yaml
*.pyc
.vscode
.venv

notes.md
can.log
59 changes: 47 additions & 12 deletions esphome/components/toptronic/toptronic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,19 +306,57 @@ void log_response_frame(std::vector<uint8_t> data, uint32_t can_id, std::string
}

void TopTronic::parse_frame(std::vector<uint8_t> 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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t> 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;
}

Expand All @@ -330,9 +368,9 @@ void TopTronic::parse_frame(std::vector<uint8_t> 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) {
Expand All @@ -342,18 +380,15 @@ void TopTronic::parse_frame(std::vector<uint8_t> data, uint32_t can_id, bool rem

if (sensorBase->type() == SENSOR) {
TopTronicSensor *sensor = (TopTronicSensor*)sensorBase;
float value = sensor->parse_value(std::vector<uint8_t>(data.begin() + 6, data.end()));
float value = sensor->parse_value(std::vector<uint8_t>(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<uint8_t>(data.begin() + 6, data.end()));
std::string value = sensor->parse_value(std::vector<uint8_t>(data.begin() + 5, data.end()));
sensor->publish_state(value);
log_response_frame(data, can_id, sensor->get_name());
}



}

} // namespace toptronic
Expand Down
3 changes: 3 additions & 0 deletions esphome/components/toptronic/toptronic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint8_t> data, uint32_t can_id, bool remote_transmission_request);

canbus::Canbus *canbus_;
std::map<uint32_t, TopTronicDevice*> devices_;
// msg_header -> (data, number of pending messages)
std::map<uint8_t, std::pair<std::vector<uint8_t>, uint8_t>> pending_messages_;

uint16_t device_type_;
uint8_t device_addr_;
Expand Down
5 changes: 5 additions & 0 deletions esphome/hoval_data_processing/generate_presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import openpyxl
from openpyxl import Workbook
from typing import Callable, Optional
import re

PatchFunc = Callable[[list[Datapoint], str], None]

Expand All @@ -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)

Expand Down

0 comments on commit 1ab146a

Please sign in to comment.