ESPHome  2024.11.1
vbus.cpp
Go to the documentation of this file.
1 #include "vbus.h"
2 #include "esphome/core/helpers.h"
3 #include "esphome/core/log.h"
4 #include <cinttypes>
5 
6 namespace esphome {
7 namespace vbus {
8 
9 static const char *const TAG = "vbus";
10 
12  ESP_LOGCONFIG(TAG, "VBus:");
13  check_uart_settings(9600);
14 }
15 
16 static void septet_spread(uint8_t *data, int start, int count, uint8_t septet) {
17  for (int i = 0; i < count; i++, septet >>= 1) {
18  if (septet & 1)
19  data[start + i] |= 0x80;
20  }
21 }
22 
23 static bool checksum(const uint8_t *data, int start, int count) {
24  uint8_t csum = 0x7f;
25  for (int i = 0; i < count; i++)
26  csum = (csum - data[start + i]) & 0x7f;
27  return csum == 0;
28 }
29 
30 void VBus::loop() {
31  if (!available())
32  return;
33 
34  while (available()) {
35  uint8_t c;
36  read_byte(&c);
37 
38  if (c == 0xaa) {
39  this->state_ = 1;
40  this->buffer_.clear();
41  continue;
42  }
43  if (c & 0x80) {
44  this->state_ = 0;
45  continue;
46  }
47  if (this->state_ == 0)
48  continue;
49 
50  if (this->state_ == 1) {
51  this->buffer_.push_back(c);
52  if (this->buffer_.size() == 7) {
53  this->protocol_ = this->buffer_[4];
54  this->source_ = (this->buffer_[3] << 8) + this->buffer_[2];
55  this->dest_ = (this->buffer_[1] << 8) + this->buffer_[0];
56  this->command_ = (this->buffer_[6] << 8) + this->buffer_[5];
57  }
58  if ((this->protocol_ == 0x20) && (this->buffer_.size() == 15)) {
59  this->state_ = 0;
60  if (!checksum(this->buffer_.data(), 0, 15)) {
61  ESP_LOGE(TAG, "P2 checksum failed");
62  continue;
63  }
64  septet_spread(this->buffer_.data(), 7, 6, this->buffer_[13]);
65  uint16_t id = (this->buffer_[8] << 8) + this->buffer_[7];
66  uint32_t value =
67  (this->buffer_[12] << 24) + (this->buffer_[11] << 16) + (this->buffer_[10] << 8) + this->buffer_[9];
68  ESP_LOGV(TAG, "P1 C%04x %04x->%04x: %04x %04" PRIx32 " (%" PRIu32 ")", this->command_, this->source_,
69  this->dest_, id, value, value);
70  } else if ((this->protocol_ == 0x10) && (this->buffer_.size() == 9)) {
71  if (!checksum(this->buffer_.data(), 0, 9)) {
72  ESP_LOGE(TAG, "P1 checksum failed");
73  this->state_ = 0;
74  continue;
75  }
76  this->frames_ = this->buffer_[7];
77  if (this->frames_) {
78  this->state_ = 2;
79  this->cframe_ = 0;
80  this->fbcount_ = 0;
81  this->buffer_.clear();
82  } else {
83  this->state_ = 0;
84  ESP_LOGD(TAG, "P1 empty message");
85  }
86  }
87  continue;
88  }
89 
90  if (this->state_ == 2) {
91  this->fbytes_[this->fbcount_++] = c;
92  if (this->fbcount_ < 6)
93  continue;
94  this->fbcount_ = 0;
95  if (!checksum(this->fbytes_, 0, 6)) {
96  ESP_LOGE(TAG, "frame checksum failed");
97  continue;
98  }
99  septet_spread(this->fbytes_, 0, 4, this->fbytes_[4]);
100  for (int i = 0; i < 4; i++)
101  this->buffer_.push_back(this->fbytes_[i]);
102  if (++this->cframe_ < this->frames_)
103  continue;
104  ESP_LOGV(TAG, "P2 C%04x %04x->%04x: %s", this->command_, this->source_, this->dest_,
105  format_hex(this->buffer_).c_str());
106  for (auto &listener : this->listeners_)
107  listener->on_message(this->command_, this->source_, this->dest_, this->buffer_);
108  this->state_ = 0;
109  continue;
110  }
111  }
112 }
113 
114 void VBusListener::on_message(uint16_t command, uint16_t source, uint16_t dest, std::vector<uint8_t> &message) {
115  if ((this->command_ != 0xffff) && (this->command_ != command))
116  return;
117  if ((this->source_ != 0xffff) && (this->source_ != source))
118  return;
119  if ((this->dest_ != 0xffff) && (this->dest_ != dest))
120  return;
121  this->handle_message(message);
122 }
123 
124 } // namespace vbus
125 } // namespace esphome
uint16_t command_
Definition: vbus.h:43
uint8_t fbytes_[6]
Definition: vbus.h:46
std::string format_hex(const uint8_t *data, size_t length)
Format the byte array data of length len in lowercased hex.
Definition: helpers.cpp:352
std::vector< VBusListener * > listeners_
Definition: vbus.h:48
uint8_t protocol_
Definition: vbus.h:40
uint8_t checksum
Definition: bl0906.h:210
void on_message(uint16_t command, uint16_t source, uint16_t dest, std::vector< uint8_t > &message)
Definition: vbus.cpp:114
uint8_t frames_
Definition: vbus.h:44
void loop() override
Definition: vbus.cpp:30
const char *const TAG
Definition: spi.cpp:8
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:13
uint16_t dest_
Definition: vbus.h:42
std::vector< uint8_t > buffer_
Definition: vbus.h:39
bool read_byte(uint8_t *data)
Definition: uart.h:29
uint8_t cframe_
Definition: vbus.h:45
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
uint16_t source_
Definition: vbus.h:41
void dump_config() override
Definition: vbus.cpp:11