ESPHome  2023.5.5
daly_bms.cpp
Go to the documentation of this file.
1 #include "daly_bms.h"
2 #include "esphome/core/log.h"
3 #include <vector>
4 
5 namespace esphome {
6 namespace daly_bms {
7 
8 static const char *const TAG = "daly_bms";
9 
10 static const uint8_t DALY_FRAME_SIZE = 13;
11 static const uint8_t DALY_TEMPERATURE_OFFSET = 40;
12 static const uint16_t DALY_CURRENT_OFFSET = 30000;
13 
14 static const uint8_t DALY_REQUEST_BATTERY_LEVEL = 0x90;
15 static const uint8_t DALY_REQUEST_MIN_MAX_VOLTAGE = 0x91;
16 static const uint8_t DALY_REQUEST_MIN_MAX_TEMPERATURE = 0x92;
17 static const uint8_t DALY_REQUEST_MOS = 0x93;
18 static const uint8_t DALY_REQUEST_STATUS = 0x94;
19 static const uint8_t DALY_REQUEST_CELL_VOLTAGE = 0x95;
20 static const uint8_t DALY_REQUEST_TEMPERATURE = 0x96;
21 
23 
25  ESP_LOGCONFIG(TAG, "Daly BMS:");
26  this->check_uart_settings(9600);
27 }
28 
30  this->request_data_(DALY_REQUEST_BATTERY_LEVEL);
31  this->request_data_(DALY_REQUEST_MIN_MAX_VOLTAGE);
32  this->request_data_(DALY_REQUEST_MIN_MAX_TEMPERATURE);
33  this->request_data_(DALY_REQUEST_MOS);
34  this->request_data_(DALY_REQUEST_STATUS);
35  this->request_data_(DALY_REQUEST_CELL_VOLTAGE);
36  this->request_data_(DALY_REQUEST_TEMPERATURE);
37 
38  std::vector<uint8_t> get_battery_level_data;
39  int available_data = this->available();
40  if (available_data >= DALY_FRAME_SIZE) {
41  get_battery_level_data.resize(available_data);
42  this->read_array(get_battery_level_data.data(), available_data);
43  this->decode_data_(get_battery_level_data);
44  }
45 }
46 
48 
49 void DalyBmsComponent::request_data_(uint8_t data_id) {
50  uint8_t request_message[DALY_FRAME_SIZE];
51 
52  request_message[0] = 0xA5; // Start Flag
53  request_message[1] = addr_; // Communication Module Address
54  request_message[2] = data_id; // Data ID
55  request_message[3] = 0x08; // Data Length (Fixed)
56  request_message[4] = 0x00; // Empty Data
57  request_message[5] = 0x00; // |
58  request_message[6] = 0x00; // |
59  request_message[7] = 0x00; // |
60  request_message[8] = 0x00; // |
61  request_message[9] = 0x00; // |
62  request_message[10] = 0x00; // |
63  request_message[11] = 0x00; // Empty Data
64  request_message[12] = (uint8_t) (request_message[0] + request_message[1] + request_message[2] +
65  request_message[3]); // Checksum (Lower byte of the other bytes sum)
66 
67  this->write_array(request_message, sizeof(request_message));
68  this->flush();
69 }
70 
71 void DalyBmsComponent::decode_data_(std::vector<uint8_t> data) {
72  auto it = data.begin();
73 
74  while ((it = std::find(it, data.end(), 0xA5)) != data.end()) {
75  if (data.end() - it >= DALY_FRAME_SIZE && it[1] == 0x01) {
76  uint8_t checksum;
77  int sum = 0;
78  for (int i = 0; i < 12; i++) {
79  sum += it[i];
80  }
81  checksum = sum;
82 
83  if (checksum == it[12]) {
84  switch (it[2]) {
85  case DALY_REQUEST_BATTERY_LEVEL:
86  if (this->voltage_sensor_) {
87  this->voltage_sensor_->publish_state((float) encode_uint16(it[4], it[5]) / 10);
88  }
89  if (this->current_sensor_) {
90  this->current_sensor_->publish_state(((float) (encode_uint16(it[8], it[9]) - DALY_CURRENT_OFFSET) / 10));
91  }
92  if (this->battery_level_sensor_) {
93  this->battery_level_sensor_->publish_state((float) encode_uint16(it[10], it[11]) / 10);
94  }
95  break;
96 
97  case DALY_REQUEST_MIN_MAX_VOLTAGE:
98  if (this->max_cell_voltage_) {
99  this->max_cell_voltage_->publish_state((float) encode_uint16(it[4], it[5]) / 1000);
100  }
101  if (this->max_cell_voltage_number_) {
103  }
104  if (this->min_cell_voltage_) {
105  this->min_cell_voltage_->publish_state((float) encode_uint16(it[7], it[8]) / 1000);
106  }
107  if (this->min_cell_voltage_number_) {
109  }
110  break;
111 
112  case DALY_REQUEST_MIN_MAX_TEMPERATURE:
113  if (this->max_temperature_) {
114  this->max_temperature_->publish_state(it[4] - DALY_TEMPERATURE_OFFSET);
115  }
116  if (this->max_temperature_probe_number_) {
118  }
119  if (this->min_temperature_) {
120  this->min_temperature_->publish_state(it[6] - DALY_TEMPERATURE_OFFSET);
121  }
122  if (this->min_temperature_probe_number_) {
124  }
125  break;
126 
127  case DALY_REQUEST_MOS:
128  if (this->status_text_sensor_ != nullptr) {
129  switch (it[4]) {
130  case 0:
131  this->status_text_sensor_->publish_state("Stationary");
132  break;
133  case 1:
134  this->status_text_sensor_->publish_state("Charging");
135  break;
136  case 2:
137  this->status_text_sensor_->publish_state("Discharging");
138  break;
139  default:
140  break;
141  }
142  }
143  if (this->charging_mos_enabled_) {
144  this->charging_mos_enabled_->publish_state(it[5]);
145  }
146  if (this->discharging_mos_enabled_) {
148  }
149  if (this->remaining_capacity_) {
150  this->remaining_capacity_->publish_state((float) encode_uint32(it[8], it[9], it[10], it[11]) / 1000);
151  }
152  break;
153 
154  case DALY_REQUEST_STATUS:
155  if (this->cells_number_) {
156  this->cells_number_->publish_state(it[4]);
157  }
158  break;
159 
160  case DALY_REQUEST_TEMPERATURE:
161  if (it[4] == 1) {
162  if (this->temperature_1_sensor_) {
163  this->temperature_1_sensor_->publish_state(it[5] - DALY_TEMPERATURE_OFFSET);
164  }
165  if (this->temperature_2_sensor_) {
166  this->temperature_2_sensor_->publish_state(it[6] - DALY_TEMPERATURE_OFFSET);
167  }
168  }
169  break;
170 
171  case DALY_REQUEST_CELL_VOLTAGE:
172  switch (it[4]) {
173  case 1:
174  if (this->cell_1_voltage_) {
175  this->cell_1_voltage_->publish_state((float) encode_uint16(it[5], it[6]) / 1000);
176  }
177  if (this->cell_2_voltage_) {
178  this->cell_2_voltage_->publish_state((float) encode_uint16(it[7], it[8]) / 1000);
179  }
180  if (this->cell_3_voltage_) {
181  this->cell_3_voltage_->publish_state((float) encode_uint16(it[9], it[10]) / 1000);
182  }
183  break;
184  case 2:
185  if (this->cell_4_voltage_) {
186  this->cell_4_voltage_->publish_state((float) encode_uint16(it[5], it[6]) / 1000);
187  }
188  if (this->cell_5_voltage_) {
189  this->cell_5_voltage_->publish_state((float) encode_uint16(it[7], it[8]) / 1000);
190  }
191  if (this->cell_6_voltage_) {
192  this->cell_6_voltage_->publish_state((float) encode_uint16(it[9], it[10]) / 1000);
193  }
194  break;
195  case 3:
196  if (this->cell_7_voltage_) {
197  this->cell_7_voltage_->publish_state((float) encode_uint16(it[5], it[6]) / 1000);
198  }
199  if (this->cell_8_voltage_) {
200  this->cell_8_voltage_->publish_state((float) encode_uint16(it[7], it[8]) / 1000);
201  }
202  if (this->cell_9_voltage_) {
203  this->cell_9_voltage_->publish_state((float) encode_uint16(it[9], it[10]) / 1000);
204  }
205  break;
206  case 4:
207  if (this->cell_10_voltage_) {
208  this->cell_10_voltage_->publish_state((float) encode_uint16(it[5], it[6]) / 1000);
209  }
210  if (this->cell_11_voltage_) {
211  this->cell_11_voltage_->publish_state((float) encode_uint16(it[7], it[8]) / 1000);
212  }
213  if (this->cell_12_voltage_) {
214  this->cell_12_voltage_->publish_state((float) encode_uint16(it[9], it[10]) / 1000);
215  }
216  break;
217  case 5:
218  if (this->cell_13_voltage_) {
219  this->cell_13_voltage_->publish_state((float) encode_uint16(it[5], it[6]) / 1000);
220  }
221  if (this->cell_14_voltage_) {
222  this->cell_14_voltage_->publish_state((float) encode_uint16(it[7], it[8]) / 1000);
223  }
224  if (this->cell_15_voltage_) {
225  this->cell_15_voltage_->publish_state((float) encode_uint16(it[9], it[10]) / 1000);
226  }
227  break;
228  case 6:
229  if (this->cell_16_voltage_) {
230  this->cell_16_voltage_->publish_state((float) encode_uint16(it[5], it[6]) / 1000);
231  }
232  break;
233  }
234  break;
235 
236  default:
237  break;
238  }
239  }
240  std::advance(it, DALY_FRAME_SIZE);
241  } else {
242  std::advance(it, 1);
243  }
244  }
245 }
246 
247 } // namespace daly_bms
248 } // namespace esphome
sensor::Sensor * cell_15_voltage_
Definition: daly_bms.h:111
sensor::Sensor * min_temperature_probe_number_
Definition: daly_bms.h:92
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:18
sensor::Sensor * max_cell_voltage_number_
Definition: daly_bms.h:86
optional< std::array< uint8_t, N > > read_array()
Definition: uart.h:33
void write_array(const uint8_t *data, size_t len)
Definition: uart.h:21
sensor::Sensor * remaining_capacity_
Definition: daly_bms.h:93
sensor::Sensor * temperature_2_sensor_
Definition: daly_bms.h:96
sensor::Sensor * temperature_1_sensor_
Definition: daly_bms.h:95
sensor::Sensor * current_sensor_
Definition: daly_bms.h:83
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
Definition: helpers.h:180
sensor::Sensor * min_cell_voltage_
Definition: daly_bms.h:87
void publish_state(const std::string &state)
Definition: text_sensor.cpp:9
binary_sensor::BinarySensor * discharging_mos_enabled_
Definition: daly_bms.h:117
sensor::Sensor * cell_5_voltage_
Definition: daly_bms.h:101
sensor::Sensor * min_cell_voltage_number_
Definition: daly_bms.h:88
sensor::Sensor * cell_6_voltage_
Definition: daly_bms.h:102
sensor::Sensor * cell_8_voltage_
Definition: daly_bms.h:104
sensor::Sensor * cell_11_voltage_
Definition: daly_bms.h:107
void request_data_(uint8_t data_id)
Definition: daly_bms.cpp:49
sensor::Sensor * cell_10_voltage_
Definition: daly_bms.h:106
sensor::Sensor * cell_16_voltage_
Definition: daly_bms.h:112
void check_uart_settings(uint32_t baud_rate, uint8_t stop_bits=1, UARTParityOptions parity=UART_CONFIG_PARITY_NONE, uint8_t data_bits=8)
Check that the configuration of the UART bus matches the provided values and otherwise print a warnin...
Definition: uart.cpp:12
text_sensor::TextSensor * status_text_sensor_
Definition: daly_bms.h:114
sensor::Sensor * voltage_sensor_
Definition: daly_bms.h:82
void decode_data_(std::vector< uint8_t > data)
Definition: daly_bms.cpp:71
sensor::Sensor * cell_4_voltage_
Definition: daly_bms.h:100
sensor::Sensor * min_temperature_
Definition: daly_bms.h:91
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
sensor::Sensor * max_temperature_probe_number_
Definition: daly_bms.h:90
sensor::Sensor * cell_3_voltage_
Definition: daly_bms.h:99
sensor::Sensor * max_cell_voltage_
Definition: daly_bms.h:85
sensor::Sensor * battery_level_sensor_
Definition: daly_bms.h:84
binary_sensor::BinarySensor * charging_mos_enabled_
Definition: daly_bms.h:116
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition: helpers.h:176
void publish_state(bool state)
Publish a new state to the front-end.
uint8_t checksum
Definition: bl0939.h:35
sensor::Sensor * cell_9_voltage_
Definition: daly_bms.h:105
sensor::Sensor * cell_2_voltage_
Definition: daly_bms.h:98
sensor::Sensor * cell_13_voltage_
Definition: daly_bms.h:109
sensor::Sensor * cell_14_voltage_
Definition: daly_bms.h:110
sensor::Sensor * cells_number_
Definition: daly_bms.h:94
float get_setup_priority() const override
Definition: daly_bms.cpp:47
Definition: a4988.cpp:4
sensor::Sensor * cell_12_voltage_
Definition: daly_bms.h:108
sensor::Sensor * max_temperature_
Definition: daly_bms.h:89
sensor::Sensor * cell_7_voltage_
Definition: daly_bms.h:103
sensor::Sensor * cell_1_voltage_
Definition: daly_bms.h:97