ESPHome  2024.5.0
dfrobot_sen0395.cpp
Go to the documentation of this file.
1 #include "dfrobot_sen0395.h"
2 
3 #include "esphome/core/helpers.h"
4 #include "esphome/core/log.h"
5 
6 namespace esphome {
7 namespace dfrobot_sen0395 {
8 
9 static const char *const TAG = "dfrobot_sen0395";
10 const char ASCII_CR = 0x0D;
11 const char ASCII_LF = 0x0A;
12 
14  ESP_LOGCONFIG(TAG, "Dfrobot Mmwave Radar:");
15 #ifdef USE_BINARY_SENSOR
16  LOG_BINARY_SENSOR(" ", "Registered", this->detected_binary_sensor_);
17 #endif
18 #ifdef USE_SWITCH
19  LOG_SWITCH(" ", "Sensor Active Switch", this->sensor_active_switch_);
20  LOG_SWITCH(" ", "Turn on LED Switch", this->turn_on_led_switch_);
21  LOG_SWITCH(" ", "Presence via UART Switch", this->presence_via_uart_switch_);
22  LOG_SWITCH(" ", "Start after Boot Switch", this->start_after_boot_switch_);
23 #endif
24 }
25 
26 void DfrobotSen0395Component::loop() {
27  if (cmd_queue_.is_empty()) {
28  // Command queue empty. Read sensor state.
29  cmd_queue_.enqueue(make_unique<ReadStateCommand>());
30  }
31 
32  // Commands are non-blocking and need to be called repeatedly.
33  if (cmd_queue_.process(this)) {
34  // Dequeue if command is done
36  }
37 }
38 
39 int8_t DfrobotSen0395Component::enqueue(std::unique_ptr<Command> cmd) {
40  return cmd_queue_.enqueue(std::move(cmd)); // Transfer ownership using std::move
41 }
42 
44  while (this->available()) {
45  uint8_t byte;
46  this->read_byte(&byte);
47 
49  this->read_pos_ = 0;
50 
51  ESP_LOGVV(TAG, "Buffer pos: %u %d", this->read_pos_, byte);
52 
53  if (byte == ASCII_CR)
54  continue;
55  if (byte >= 0x7F)
56  byte = '?'; // needs to be valid utf8 string for log functions.
57  this->read_buffer_[this->read_pos_] = byte;
58 
59  if (this->read_pos_ == 9 && byte == '>')
60  this->read_buffer_[++this->read_pos_] = ASCII_LF;
61 
62  if (this->read_buffer_[this->read_pos_] == ASCII_LF) {
63  this->read_buffer_[this->read_pos_] = 0;
64  this->read_pos_ = 0;
65  ESP_LOGV(TAG, "Message: %s", this->read_buffer_);
66  return 1; // Full message in buffer
67  } else {
68  this->read_pos_++;
69  }
70  }
71  return 0; // No full message yet
72 }
73 
75  if (this->read_message_()) {
76  std::string message(this->read_buffer_);
77  if (message.rfind("leapMMW:/>") != std::string::npos) {
78  return 1; // Prompt found
79  }
80  }
81  return 0; // Not found yet
82 }
83 
84 uint8_t DfrobotSen0395Component::send_cmd_(const char *cmd, uint32_t duration) {
85  // The interval between two commands must be larger than the specified duration (in ms).
86  if (millis() - ts_last_cmd_sent_ > duration) {
87  this->write_str(cmd);
89  return 1; // Command sent
90  }
91  // Could not send command yet as command duration did not fully pass yet.
92  return 0;
93 }
94 
96  this->detected_ = detected;
97 #ifdef USE_BINARY_SENSOR
98  if (this->detected_binary_sensor_ != nullptr)
99  this->detected_binary_sensor_->publish_state(detected);
100 #endif
101 }
102 
103 int8_t CircularCommandQueue::enqueue(std::unique_ptr<Command> cmd) {
104  if (this->is_full()) {
105  ESP_LOGE(TAG, "Command queue is full");
106  return -1;
107  } else if (this->is_empty())
108  front_++;
109  rear_ = (rear_ + 1) % COMMAND_QUEUE_SIZE;
110  commands_[rear_] = std::move(cmd); // Transfer ownership using std::move
111  return 1;
112 }
113 
114 std::unique_ptr<Command> CircularCommandQueue::dequeue() {
115  if (this->is_empty())
116  return nullptr;
117  std::unique_ptr<Command> dequeued_cmd = std::move(commands_[front_]);
118  if (front_ == rear_) {
119  front_ = -1;
120  rear_ = -1;
121  } else
122  front_ = (front_ + 1) % COMMAND_QUEUE_SIZE;
123 
124  return dequeued_cmd;
125 }
126 
127 bool CircularCommandQueue::is_empty() { return front_ == -1; }
128 
129 bool CircularCommandQueue::is_full() { return (rear_ + 1) % COMMAND_QUEUE_SIZE == front_; }
130 
131 // Run execute method of first in line command.
132 // Execute is non-blocking and has to be called until it returns 1.
134  if (!is_empty()) {
135  return commands_[front_]->execute(parent);
136  } else {
137  return 1;
138  }
139 }
140 
141 } // namespace dfrobot_sen0395
142 } // namespace esphome
void write_str(const char *str)
Definition: uart.h:27
virtual void dump_config()
Definition: component.cpp:186
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
binary_sensor::BinarySensor * detected_binary_sensor_
uint8_t send_cmd_(const char *cmd, uint32_t duration)
bool read_byte(uint8_t *data)
Definition: uart.h:29
uint8_t process(DfrobotSen0395Component *parent)
char read_buffer_[MMWAVE_READ_BUFFER_LENGTH]
void publish_state(bool state)
Publish a new state to the front-end.
int8_t enqueue(std::unique_ptr< Command > cmd)
const uint8_t MMWAVE_READ_BUFFER_LENGTH
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
stm32_cmd_t * cmd
Definition: stm32flash.h:96