ESPHome  2024.5.0
micronova.cpp
Go to the documentation of this file.
1 #include "micronova.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace micronova {
6 
8  if (this->enable_rx_pin_ != nullptr) {
9  this->enable_rx_pin_->setup();
11  this->enable_rx_pin_->digital_write(false);
12  }
18 }
19 
21  ESP_LOGCONFIG(TAG, "MicroNova:");
22  if (this->enable_rx_pin_ != nullptr) {
23  LOG_PIN(" Enable RX Pin: ", this->enable_rx_pin_);
24  }
25 
26  for (auto &mv_sensor : this->micronova_listeners_) {
27  mv_sensor->dump_config();
28  ESP_LOGCONFIG(TAG, " sensor location:%02X, address:%02X", mv_sensor->get_memory_location(),
29  mv_sensor->get_memory_address());
30  }
31 }
32 
34  ESP_LOGD(TAG, "Schedule sensor update");
35  for (auto &mv_listener : this->micronova_listeners_) {
36  mv_listener->set_needs_update(true);
37  }
38 }
39 
41  // Only read one sensor that needs update per loop
42  // If STOVE_REPLY_DELAY time has passed since last loop()
43  // check for a reply from the stove
45  (millis() - this->current_transmission_.request_transmission_time > STOVE_REPLY_DELAY)) {
46  int stove_reply_value = this->read_stove_reply();
47  if (this->current_transmission_.initiating_listener != nullptr) {
50  }
52  return;
53  } else if (!this->current_transmission_.reply_pending) {
54  for (auto &mv_listener : this->micronova_listeners_) {
55  if (mv_listener->get_needs_update()) {
56  mv_listener->set_needs_update(false);
57  this->current_transmission_.initiating_listener = mv_listener;
58  mv_listener->request_value_from_stove();
59  return;
60  }
61  }
62  }
63 }
64 
65 void MicroNova::request_address(uint8_t location, uint8_t address, MicroNovaSensorListener *listener) {
66  uint8_t write_data[2] = {0, 0};
67  uint8_t trash_rx;
68 
69  if (this->reply_pending_mutex_.try_lock()) {
70  // clear rx buffer.
71  // Stove hickups may cause late replies in the rx
72  while (this->available()) {
73  this->read_byte(&trash_rx);
74  ESP_LOGW(TAG, "Reading excess byte 0x%02X", trash_rx);
75  }
76 
77  write_data[0] = location;
78  write_data[1] = address;
79  ESP_LOGV(TAG, "Request from stove [%02X,%02X]", write_data[0], write_data[1]);
80 
81  this->enable_rx_pin_->digital_write(true);
82  this->write_array(write_data, 2);
83  this->flush();
84  this->enable_rx_pin_->digital_write(false);
85 
87  this->current_transmission_.memory_location = location;
88  this->current_transmission_.memory_address = address;
91  } else {
92  ESP_LOGE(TAG, "Reply is pending, skipping read request");
93  }
94 }
95 
97  uint8_t reply_data[2] = {0, 0};
98  uint8_t checksum = 0;
99 
100  // assert enable_rx_pin is false
101  this->read_array(reply_data, 2);
102 
104  ESP_LOGV(TAG, "Reply from stove [%02X,%02X]", reply_data[0], reply_data[1]);
105 
106  checksum = ((uint16_t) this->current_transmission_.memory_location +
107  (uint16_t) this->current_transmission_.memory_address + (uint16_t) reply_data[1]) &
108  0xFF;
109  if (reply_data[0] != checksum) {
110  ESP_LOGE(TAG, "Checksum missmatch! From [0x%02X:0x%02X] received [0x%02X,0x%02X]. Expected 0x%02X, got 0x%02X",
111  this->current_transmission_.memory_location, this->current_transmission_.memory_address, reply_data[0],
112  reply_data[1], checksum, reply_data[0]);
113  return -1;
114  }
115  return ((int) reply_data[1]);
116 }
117 
118 void MicroNova::write_address(uint8_t location, uint8_t address, uint8_t data) {
119  uint8_t write_data[4] = {0, 0, 0, 0};
120  uint16_t checksum = 0;
121 
122  if (this->reply_pending_mutex_.try_lock()) {
123  write_data[0] = location;
124  write_data[1] = address;
125  write_data[2] = data;
126 
127  checksum = ((uint16_t) write_data[0] + (uint16_t) write_data[1] + (uint16_t) write_data[2]) & 0xFF;
128  write_data[3] = checksum;
129 
130  ESP_LOGV(TAG, "Write 4 bytes [%02X,%02X,%02X,%02X]", write_data[0], write_data[1], write_data[2], write_data[3]);
131 
132  this->enable_rx_pin_->digital_write(true);
133  this->write_array(write_data, 4);
134  this->flush();
135  this->enable_rx_pin_->digital_write(false);
136 
138  this->current_transmission_.memory_location = location;
139  this->current_transmission_.memory_address = address;
142  } else {
143  ESP_LOGE(TAG, "Reply is pending, skipping write");
144  }
145 }
146 
147 } // namespace micronova
148 } // namespace esphome
virtual void digital_write(bool value)=0
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
void dump_config() override
Definition: micronova.cpp:20
virtual void pin_mode(gpio::Flags flags)=0
void write_address(uint8_t location, uint8_t address, uint8_t data)
Definition: micronova.cpp:118
virtual void setup()=0
MicroNovaSerialTransmission current_transmission_
Definition: micronova.h:157
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
std::vector< MicroNovaSensorListener * > micronova_listeners_
Definition: micronova.h:159
bool read_byte(uint8_t *data)
Definition: uart.h:29
void request_address(uint8_t location, uint8_t address, MicroNovaSensorListener *listener)
Definition: micronova.cpp:65
uint8_t checksum
Definition: bl0939.h:35
bool try_lock()
Definition: helpers.cpp:621
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void unlock()
Definition: helpers.cpp:622
virtual void process_value_from_stove(int value_from_stove)=0