148 lines
5.2 KiB
C++
148 lines
5.2 KiB
C++
#include "micronova.h"
|
|
#include "esphome/core/log.h"
|
|
|
|
namespace esphome {
|
|
namespace micronova {
|
|
|
|
void MicroNova::setup() {
|
|
if (this->enable_rx_pin_ != nullptr) {
|
|
this->enable_rx_pin_->setup();
|
|
this->enable_rx_pin_->pin_mode(gpio::FLAG_OUTPUT);
|
|
this->enable_rx_pin_->digital_write(false);
|
|
}
|
|
this->current_transmission_.request_transmission_time = millis();
|
|
this->current_transmission_.memory_location = 0;
|
|
this->current_transmission_.memory_address = 0;
|
|
this->current_transmission_.reply_pending = false;
|
|
this->current_transmission_.initiating_listener = nullptr;
|
|
}
|
|
|
|
void MicroNova::dump_config() {
|
|
ESP_LOGCONFIG(TAG, "MicroNova:");
|
|
if (this->enable_rx_pin_ != nullptr) {
|
|
LOG_PIN(" Enable RX Pin: ", this->enable_rx_pin_);
|
|
}
|
|
|
|
for (auto &mv_sensor : this->micronova_listeners_) {
|
|
mv_sensor->dump_config();
|
|
ESP_LOGCONFIG(TAG, " sensor location:%02X, address:%02X", mv_sensor->get_memory_location(),
|
|
mv_sensor->get_memory_address());
|
|
}
|
|
}
|
|
|
|
void MicroNova::update() {
|
|
ESP_LOGD(TAG, "Schedule sensor update");
|
|
for (auto &mv_listener : this->micronova_listeners_) {
|
|
mv_listener->set_needs_update(true);
|
|
}
|
|
}
|
|
|
|
void MicroNova::loop() {
|
|
// Only read one sensor that needs update per loop
|
|
// If STOVE_REPLY_DELAY time has passed since last loop()
|
|
// check for a reply from the stove
|
|
if ((this->current_transmission_.reply_pending) &&
|
|
(millis() - this->current_transmission_.request_transmission_time > STOVE_REPLY_DELAY)) {
|
|
int stove_reply_value = this->read_stove_reply();
|
|
if (this->current_transmission_.initiating_listener != nullptr) {
|
|
this->current_transmission_.initiating_listener->process_value_from_stove(stove_reply_value);
|
|
this->current_transmission_.initiating_listener = nullptr;
|
|
}
|
|
this->current_transmission_.reply_pending = false;
|
|
return;
|
|
} else if (!this->current_transmission_.reply_pending) {
|
|
for (auto &mv_listener : this->micronova_listeners_) {
|
|
if (mv_listener->get_needs_update()) {
|
|
mv_listener->set_needs_update(false);
|
|
this->current_transmission_.initiating_listener = mv_listener;
|
|
mv_listener->request_value_from_stove();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MicroNova::request_address(uint8_t location, uint8_t address, MicroNovaSensorListener *listener) {
|
|
uint8_t write_data[2] = {0, 0};
|
|
uint8_t trash_rx;
|
|
|
|
if (this->reply_pending_mutex_.try_lock()) {
|
|
// clear rx buffer.
|
|
// Stove hickups may cause late replies in the rx
|
|
while (this->available()) {
|
|
this->read_byte(&trash_rx);
|
|
ESP_LOGW(TAG, "Reading excess byte 0x%02X", trash_rx);
|
|
}
|
|
|
|
write_data[0] = location;
|
|
write_data[1] = address;
|
|
ESP_LOGV(TAG, "Request from stove [%02X,%02X]", write_data[0], write_data[1]);
|
|
|
|
this->enable_rx_pin_->digital_write(true);
|
|
this->write_array(write_data, 2);
|
|
this->flush();
|
|
this->enable_rx_pin_->digital_write(false);
|
|
|
|
this->current_transmission_.request_transmission_time = millis();
|
|
this->current_transmission_.memory_location = location;
|
|
this->current_transmission_.memory_address = address;
|
|
this->current_transmission_.reply_pending = true;
|
|
this->current_transmission_.initiating_listener = listener;
|
|
} else {
|
|
ESP_LOGE(TAG, "Reply is pending, skipping read request");
|
|
}
|
|
}
|
|
|
|
int MicroNova::read_stove_reply() {
|
|
uint8_t reply_data[2] = {0, 0};
|
|
uint8_t checksum = 0;
|
|
|
|
// assert enable_rx_pin is false
|
|
this->read_array(reply_data, 2);
|
|
|
|
this->reply_pending_mutex_.unlock();
|
|
ESP_LOGV(TAG, "Reply from stove [%02X,%02X]", reply_data[0], reply_data[1]);
|
|
|
|
checksum = ((uint16_t) this->current_transmission_.memory_location +
|
|
(uint16_t) this->current_transmission_.memory_address + (uint16_t) reply_data[1]) &
|
|
0xFF;
|
|
if (reply_data[0] != checksum) {
|
|
ESP_LOGE(TAG, "Checksum missmatch! From [0x%02X:0x%02X] received [0x%02X,0x%02X]. Expected 0x%02X, got 0x%02X",
|
|
this->current_transmission_.memory_location, this->current_transmission_.memory_address, reply_data[0],
|
|
reply_data[1], checksum, reply_data[0]);
|
|
return -1;
|
|
}
|
|
return ((int) reply_data[1]);
|
|
}
|
|
|
|
void MicroNova::write_address(uint8_t location, uint8_t address, uint8_t data) {
|
|
uint8_t write_data[4] = {0, 0, 0, 0};
|
|
uint16_t checksum = 0;
|
|
|
|
if (this->reply_pending_mutex_.try_lock()) {
|
|
write_data[0] = location;
|
|
write_data[1] = address;
|
|
write_data[2] = data;
|
|
|
|
checksum = ((uint16_t) write_data[0] + (uint16_t) write_data[1] + (uint16_t) write_data[2]) & 0xFF;
|
|
write_data[3] = checksum;
|
|
|
|
ESP_LOGV(TAG, "Write 4 bytes [%02X,%02X,%02X,%02X]", write_data[0], write_data[1], write_data[2], write_data[3]);
|
|
|
|
this->enable_rx_pin_->digital_write(true);
|
|
this->write_array(write_data, 4);
|
|
this->flush();
|
|
this->enable_rx_pin_->digital_write(false);
|
|
|
|
this->current_transmission_.request_transmission_time = millis();
|
|
this->current_transmission_.memory_location = location;
|
|
this->current_transmission_.memory_address = address;
|
|
this->current_transmission_.reply_pending = true;
|
|
this->current_transmission_.initiating_listener = nullptr;
|
|
} else {
|
|
ESP_LOGE(TAG, "Reply is pending, skipping write");
|
|
}
|
|
}
|
|
|
|
} // namespace micronova
|
|
} // namespace esphome
|