ESPHome  2024.9.2
ezo_pmp.cpp
Go to the documentation of this file.
1 #include "ezo_pmp.h"
2 #include "esphome/core/log.h"
3 #include "esphome/core/hal.h"
4 
5 namespace esphome {
6 namespace ezo_pmp {
7 
8 static const char *const TAG = "ezo-pmp";
9 
10 static const uint16_t EZO_PMP_COMMAND_NONE = 0;
11 static const uint16_t EZO_PMP_COMMAND_TYPE_READ = 1;
12 
13 static const uint16_t EZO_PMP_COMMAND_FIND = 2;
14 static const uint16_t EZO_PMP_COMMAND_DOSE_CONTINUOUSLY = 4;
15 static const uint16_t EZO_PMP_COMMAND_DOSE_VOLUME = 8;
16 static const uint16_t EZO_PMP_COMMAND_DOSE_VOLUME_OVER_TIME = 16;
17 static const uint16_t EZO_PMP_COMMAND_DOSE_WITH_CONSTANT_FLOW_RATE = 32;
18 static const uint16_t EZO_PMP_COMMAND_SET_CALIBRATION_VOLUME = 64;
19 static const uint16_t EZO_PMP_COMMAND_CLEAR_TOTAL_VOLUME_DOSED = 128;
20 static const uint16_t EZO_PMP_COMMAND_CLEAR_CALIBRATION = 256;
21 static const uint16_t EZO_PMP_COMMAND_PAUSE_DOSING = 512;
22 static const uint16_t EZO_PMP_COMMAND_STOP_DOSING = 1024;
23 static const uint16_t EZO_PMP_COMMAND_CHANGE_I2C_ADDRESS = 2048;
24 static const uint16_t EZO_PMP_COMMAND_EXEC_ARBITRARY_COMMAND_ADDRESS = 4096;
25 
26 static const uint16_t EZO_PMP_COMMAND_READ_DOSING = 3;
27 static const uint16_t EZO_PMP_COMMAND_READ_SINGLE_REPORT = 5;
28 static const uint16_t EZO_PMP_COMMAND_READ_MAX_FLOW_RATE = 9;
29 static const uint16_t EZO_PMP_COMMAND_READ_PAUSE_STATUS = 17;
30 static const uint16_t EZO_PMP_COMMAND_READ_TOTAL_VOLUME_DOSED = 33;
31 static const uint16_t EZO_PMP_COMMAND_READ_ABSOLUTE_TOTAL_VOLUME_DOSED = 65;
32 static const uint16_t EZO_PMP_COMMAND_READ_CALIBRATION_STATUS = 129;
33 static const uint16_t EZO_PMP_COMMAND_READ_PUMP_VOLTAGE = 257;
34 
35 static const std::string DOSING_MODE_NONE = "None";
36 static const std::string DOSING_MODE_VOLUME = "Volume";
37 static const std::string DOSING_MODE_VOLUME_OVER_TIME = "Volume/Time";
38 static const std::string DOSING_MODE_CONSTANT_FLOW_RATE = "Constant Flow Rate";
39 static const std::string DOSING_MODE_CONTINUOUS = "Continuous";
40 
42  LOG_I2C_DEVICE(this);
43  if (this->is_failed()) {
44  ESP_LOGE(TAG, "Communication with EZO-PMP circuit failed!");
45  }
46  LOG_UPDATE_INTERVAL(this);
47 }
48 
50  if (this->is_waiting_) {
51  return;
52  }
53 
54  if (this->is_first_read_) {
55  this->queue_command_(EZO_PMP_COMMAND_READ_CALIBRATION_STATUS, 0, 0, (bool) this->calibration_status_);
56  this->queue_command_(EZO_PMP_COMMAND_READ_MAX_FLOW_RATE, 0, 0, (bool) this->max_flow_rate_);
57  this->queue_command_(EZO_PMP_COMMAND_READ_SINGLE_REPORT, 0, 0, (bool) this->current_volume_dosed_);
58  this->queue_command_(EZO_PMP_COMMAND_READ_TOTAL_VOLUME_DOSED, 0, 0, (bool) this->total_volume_dosed_);
59  this->queue_command_(EZO_PMP_COMMAND_READ_ABSOLUTE_TOTAL_VOLUME_DOSED, 0, 0,
60  (bool) this->absolute_total_volume_dosed_);
61  this->queue_command_(EZO_PMP_COMMAND_READ_PAUSE_STATUS, 0, 0, true);
62  this->is_first_read_ = false;
63  }
64 
65  if (!this->is_waiting_ && this->peek_next_command_() == EZO_PMP_COMMAND_NONE) {
66  this->queue_command_(EZO_PMP_COMMAND_READ_DOSING, 0, 0, true);
67 
68  if (this->is_dosing_flag_) {
69  this->queue_command_(EZO_PMP_COMMAND_READ_SINGLE_REPORT, 0, 0, (bool) this->current_volume_dosed_);
70  this->queue_command_(EZO_PMP_COMMAND_READ_TOTAL_VOLUME_DOSED, 0, 0, (bool) this->total_volume_dosed_);
71  this->queue_command_(EZO_PMP_COMMAND_READ_ABSOLUTE_TOTAL_VOLUME_DOSED, 0, 0,
72  (bool) this->absolute_total_volume_dosed_);
73  }
74 
75  this->queue_command_(EZO_PMP_COMMAND_READ_PUMP_VOLTAGE, 0, 0, (bool) this->pump_voltage_);
76  } else {
77  ESP_LOGV(TAG, "Not Scheduling new Command during update()");
78  }
79 }
80 
81 void EzoPMP::loop() {
82  // If we are not waiting for anything and there is no command to be sent, return
83  if (!this->is_waiting_ && this->peek_next_command_() == EZO_PMP_COMMAND_NONE) {
84  return;
85  }
86 
87  // If we are not waiting for anything and there IS a command to be sent, do it.
88  if (!this->is_waiting_ && this->peek_next_command_() != EZO_PMP_COMMAND_NONE) {
89  this->send_next_command_();
90  }
91 
92  // If we are waiting for something but it isn't ready yet, then return
93  if (this->is_waiting_ && millis() - this->start_time_ < this->wait_time_) {
94  return;
95  }
96 
97  // We are waiting for something and it should be ready.
98  this->read_command_result_();
99 }
100 
102  this->current_command_ = EZO_PMP_COMMAND_NONE;
103  this->is_waiting_ = false;
104 }
105 
107  uint8_t response_buffer[21] = {'\0'};
108 
109  response_buffer[0] = 0;
110  if (!this->read_bytes_raw(response_buffer, 20)) {
111  ESP_LOGE(TAG, "read error");
112  this->clear_current_command_();
113  return;
114  }
115 
116  switch (response_buffer[0]) {
117  case 254:
118  return; // keep waiting
119  case 1:
120  break;
121  case 2:
122  ESP_LOGE(TAG, "device returned a syntax error");
123  this->clear_current_command_();
124  return;
125  case 255:
126  ESP_LOGE(TAG, "device returned no data");
127  this->clear_current_command_();
128  return;
129  default:
130  ESP_LOGE(TAG, "device returned an unknown response: %d", response_buffer[0]);
131  this->clear_current_command_();
132  return;
133  }
134 
135  char first_parameter_buffer[10] = {'\0'};
136  char second_parameter_buffer[10] = {'\0'};
137  char third_parameter_buffer[10] = {'\0'};
138 
139  first_parameter_buffer[0] = '\0';
140  second_parameter_buffer[0] = '\0';
141  third_parameter_buffer[0] = '\0';
142 
143  int current_parameter = 1;
144 
145  size_t position_in_parameter_buffer = 0;
146  // some sensors return multiple comma-separated values, terminate string after first one
147  for (size_t i = 1; i < sizeof(response_buffer) - 1; i++) {
148  char current_char = response_buffer[i];
149 
150  if (current_char == '\0') {
151  ESP_LOGV(TAG, "Read Response from device: %s", (char *) response_buffer);
152  ESP_LOGV(TAG, "First Component: %s", (char *) first_parameter_buffer);
153  ESP_LOGV(TAG, "Second Component: %s", (char *) second_parameter_buffer);
154  ESP_LOGV(TAG, "Third Component: %s", (char *) third_parameter_buffer);
155 
156  break;
157  }
158 
159  if (current_char == ',') {
160  current_parameter++;
161  position_in_parameter_buffer = 0;
162  continue;
163  }
164 
165  switch (current_parameter) {
166  case 1:
167  first_parameter_buffer[position_in_parameter_buffer] = current_char;
168  first_parameter_buffer[position_in_parameter_buffer + 1] = '\0';
169  break;
170  case 2:
171  second_parameter_buffer[position_in_parameter_buffer] = current_char;
172  second_parameter_buffer[position_in_parameter_buffer + 1] = '\0';
173  break;
174  case 3:
175  third_parameter_buffer[position_in_parameter_buffer] = current_char;
176  third_parameter_buffer[position_in_parameter_buffer + 1] = '\0';
177  break;
178  }
179 
180  position_in_parameter_buffer++;
181  }
182 
183  auto parsed_first_parameter = parse_number<float>(first_parameter_buffer);
184  auto parsed_second_parameter = parse_number<float>(second_parameter_buffer);
185  auto parsed_third_parameter = parse_number<float>(third_parameter_buffer);
186 
187  switch (this->current_command_) {
188  // Read Commands
189  case EZO_PMP_COMMAND_READ_DOSING: // Page 54
190  if (parsed_third_parameter.has_value())
191  this->is_dosing_flag_ = parsed_third_parameter.value_or(0) == 1;
192 
193  if (this->is_dosing_)
195 
196  if (parsed_second_parameter.has_value() && this->last_volume_requested_) {
197  this->last_volume_requested_->publish_state(parsed_second_parameter.value_or(0));
198  }
199 
200  if (!this->is_dosing_flag_ && !this->is_paused_flag_) {
201  // If pump is not paused and not dispensing
202  if (this->dosing_mode_ && this->dosing_mode_->state != DOSING_MODE_NONE)
203  this->dosing_mode_->publish_state(DOSING_MODE_NONE);
204  }
205 
206  break;
207 
208  case EZO_PMP_COMMAND_READ_SINGLE_REPORT: // Single Report (page 53)
209  if (parsed_first_parameter.has_value() && (bool) this->current_volume_dosed_) {
210  this->current_volume_dosed_->publish_state(parsed_first_parameter.value_or(0));
211  }
212  break;
213 
214  case EZO_PMP_COMMAND_READ_MAX_FLOW_RATE: // Constant Flow Rate (page 57)
215  if (parsed_second_parameter.has_value() && this->max_flow_rate_)
216  this->max_flow_rate_->publish_state(parsed_second_parameter.value_or(0));
217  break;
218 
219  case EZO_PMP_COMMAND_READ_PAUSE_STATUS: // Pause (page 61)
220  if (parsed_second_parameter.has_value())
221  this->is_paused_flag_ = parsed_second_parameter.value_or(0) == 1;
222 
223  if (this->is_paused_)
225  break;
226 
227  case EZO_PMP_COMMAND_READ_TOTAL_VOLUME_DOSED: // Total Volume Dispensed (page 64)
228  if (parsed_second_parameter.has_value() && this->total_volume_dosed_)
229  this->total_volume_dosed_->publish_state(parsed_second_parameter.value_or(0));
230  break;
231 
232  case EZO_PMP_COMMAND_READ_ABSOLUTE_TOTAL_VOLUME_DOSED: // Total Volume Dispensed (page 64)
233  if (parsed_second_parameter.has_value() && this->absolute_total_volume_dosed_)
234  this->absolute_total_volume_dosed_->publish_state(parsed_second_parameter.value_or(0));
235  break;
236 
237  case EZO_PMP_COMMAND_READ_CALIBRATION_STATUS: // Calibration (page 65)
238  if (parsed_second_parameter.has_value() && this->calibration_status_) {
239  if (parsed_second_parameter.value_or(0) == 1) {
240  this->calibration_status_->publish_state("Fixed Volume");
241  } else if (parsed_second_parameter.value_or(0) == 2) {
242  this->calibration_status_->publish_state("Volume/Time");
243  } else if (parsed_second_parameter.value_or(0) == 3) {
244  this->calibration_status_->publish_state("Fixed Volume & Volume/Time");
245  } else {
246  this->calibration_status_->publish_state("Uncalibrated");
247  }
248  }
249  break;
250 
251  case EZO_PMP_COMMAND_READ_PUMP_VOLTAGE: // Pump Voltage (page 67)
252  if (parsed_second_parameter.has_value() && this->pump_voltage_)
253  this->pump_voltage_->publish_state(parsed_second_parameter.value_or(0));
254  break;
255 
256  // Non-Read Commands
257 
258  case EZO_PMP_COMMAND_DOSE_VOLUME: // Volume Dispensing (page 55)
259  if (this->dosing_mode_ && this->dosing_mode_->state != DOSING_MODE_VOLUME)
260  this->dosing_mode_->publish_state(DOSING_MODE_VOLUME);
261  break;
262 
263  case EZO_PMP_COMMAND_DOSE_VOLUME_OVER_TIME: // Dose over time (page 56)
264  if (this->dosing_mode_ && this->dosing_mode_->state != DOSING_MODE_VOLUME_OVER_TIME)
265  this->dosing_mode_->publish_state(DOSING_MODE_VOLUME_OVER_TIME);
266  break;
267 
268  case EZO_PMP_COMMAND_DOSE_WITH_CONSTANT_FLOW_RATE: // Constant Flow Rate (page 57)
269  if (this->dosing_mode_ && this->dosing_mode_->state != DOSING_MODE_CONSTANT_FLOW_RATE)
270  this->dosing_mode_->publish_state(DOSING_MODE_CONSTANT_FLOW_RATE);
271  break;
272 
273  case EZO_PMP_COMMAND_DOSE_CONTINUOUSLY: // Continuous Dispensing (page 54)
274  if (this->dosing_mode_ && this->dosing_mode_->state != DOSING_MODE_CONTINUOUS)
275  this->dosing_mode_->publish_state(DOSING_MODE_CONTINUOUS);
276  break;
277 
278  case EZO_PMP_COMMAND_STOP_DOSING: // Stop (page 62)
279  this->is_paused_flag_ = false;
280  if (this->is_paused_)
282  if (this->dosing_mode_ && this->dosing_mode_->state != DOSING_MODE_NONE)
283  this->dosing_mode_->publish_state(DOSING_MODE_NONE);
284  break;
285 
286  case EZO_PMP_COMMAND_EXEC_ARBITRARY_COMMAND_ADDRESS:
287  ESP_LOGI(TAG, "Arbitrary Command Response: %s", (char *) response_buffer);
288  break;
289 
290  case EZO_PMP_COMMAND_CLEAR_CALIBRATION: // Clear Calibration (page 65)
291  case EZO_PMP_COMMAND_PAUSE_DOSING: // Pause (page 61)
292  case EZO_PMP_COMMAND_SET_CALIBRATION_VOLUME: // Set Calibration Volume (page 65)
293  case EZO_PMP_COMMAND_CLEAR_TOTAL_VOLUME_DOSED: // Clear Total Volume Dosed (page 64)
294  case EZO_PMP_COMMAND_FIND: // Find (page 52)
295  // Nothing to do here
296  break;
297 
298  case EZO_PMP_COMMAND_TYPE_READ:
299  case EZO_PMP_COMMAND_NONE:
300  default:
301  ESP_LOGE(TAG, "Unsupported command received: %d", this->current_command_);
302  return;
303  }
304 
305  this->clear_current_command_();
306 }
307 
309  int wait_time_for_command = 400; // milliseconds
310  uint8_t command_buffer[21];
311  int command_buffer_length = 0;
312 
313  this->pop_next_command_(); // this->next_command will be updated.
314 
315  switch (this->next_command_) {
316  // Read Commands
317  case EZO_PMP_COMMAND_READ_DOSING: // Page 54
318  command_buffer_length = sprintf((char *) command_buffer, "D,?");
319  break;
320 
321  case EZO_PMP_COMMAND_READ_SINGLE_REPORT: // Single Report (page 53)
322  command_buffer_length = sprintf((char *) command_buffer, "R");
323  break;
324 
325  case EZO_PMP_COMMAND_READ_MAX_FLOW_RATE:
326  command_buffer_length = sprintf((char *) command_buffer, "DC,?");
327  break;
328 
329  case EZO_PMP_COMMAND_READ_PAUSE_STATUS:
330  command_buffer_length = sprintf((char *) command_buffer, "P,?");
331  break;
332 
333  case EZO_PMP_COMMAND_READ_TOTAL_VOLUME_DOSED:
334  command_buffer_length = sprintf((char *) command_buffer, "TV,?");
335  break;
336 
337  case EZO_PMP_COMMAND_READ_ABSOLUTE_TOTAL_VOLUME_DOSED:
338  command_buffer_length = sprintf((char *) command_buffer, "ATV,?");
339  break;
340 
341  case EZO_PMP_COMMAND_READ_CALIBRATION_STATUS:
342  command_buffer_length = sprintf((char *) command_buffer, "Cal,?");
343  break;
344 
345  case EZO_PMP_COMMAND_READ_PUMP_VOLTAGE:
346  command_buffer_length = sprintf((char *) command_buffer, "PV,?");
347  break;
348 
349  // Non-Read Commands
350 
351  case EZO_PMP_COMMAND_FIND: // Find (page 52)
352  command_buffer_length = sprintf((char *) command_buffer, "Find");
353  wait_time_for_command = 60000; // This command will block all updates for a minute
354  break;
355 
356  case EZO_PMP_COMMAND_DOSE_CONTINUOUSLY: // Continuous Dispensing (page 54)
357  command_buffer_length = sprintf((char *) command_buffer, "D,*");
358  break;
359 
360  case EZO_PMP_COMMAND_CLEAR_TOTAL_VOLUME_DOSED: // Clear Total Volume Dosed (page 64)
361  command_buffer_length = sprintf((char *) command_buffer, "Clear");
362  break;
363 
364  case EZO_PMP_COMMAND_CLEAR_CALIBRATION: // Clear Calibration (page 65)
365  command_buffer_length = sprintf((char *) command_buffer, "Cal,clear");
366  break;
367 
368  case EZO_PMP_COMMAND_PAUSE_DOSING: // Pause (page 61)
369  command_buffer_length = sprintf((char *) command_buffer, "P");
370  break;
371 
372  case EZO_PMP_COMMAND_STOP_DOSING: // Stop (page 62)
373  command_buffer_length = sprintf((char *) command_buffer, "X");
374  break;
375 
376  // Non-Read commands with parameters
377 
378  case EZO_PMP_COMMAND_DOSE_VOLUME: // Volume Dispensing (page 55)
379  command_buffer_length = sprintf((char *) command_buffer, "D,%0.1f", this->next_command_volume_);
380  break;
381 
382  case EZO_PMP_COMMAND_DOSE_VOLUME_OVER_TIME: // Dose over time (page 56)
383  command_buffer_length =
384  sprintf((char *) command_buffer, "D,%0.1f,%i", this->next_command_volume_, this->next_command_duration_);
385  break;
386 
387  case EZO_PMP_COMMAND_DOSE_WITH_CONSTANT_FLOW_RATE: // Constant Flow Rate (page 57)
388  command_buffer_length =
389  sprintf((char *) command_buffer, "DC,%0.1f,%i", this->next_command_volume_, this->next_command_duration_);
390  break;
391 
392  case EZO_PMP_COMMAND_SET_CALIBRATION_VOLUME: // Set Calibration Volume (page 65)
393  command_buffer_length = sprintf((char *) command_buffer, "Cal,%0.2f", this->next_command_volume_);
394  break;
395 
396  case EZO_PMP_COMMAND_CHANGE_I2C_ADDRESS: // Change I2C Address (page 73)
397  command_buffer_length = sprintf((char *) command_buffer, "I2C,%i", this->next_command_duration_);
398  break;
399 
400  case EZO_PMP_COMMAND_EXEC_ARBITRARY_COMMAND_ADDRESS: // Run an arbitrary command
401  command_buffer_length = sprintf((char *) command_buffer, this->arbitrary_command_, this->next_command_duration_);
402  ESP_LOGI(TAG, "Sending arbitrary command: %s", (char *) command_buffer);
403  break;
404 
405  case EZO_PMP_COMMAND_TYPE_READ:
406  case EZO_PMP_COMMAND_NONE:
407  default:
408  ESP_LOGE(TAG, "Unsupported command received: %d", this->next_command_);
409  return;
410  }
411 
412  // Send command
413  ESP_LOGV(TAG, "Sending command to device: %s", (char *) command_buffer);
414  this->write(command_buffer, command_buffer_length);
415 
416  this->current_command_ = this->next_command_;
417  this->next_command_ = EZO_PMP_COMMAND_NONE;
418  this->is_waiting_ = true;
419  this->start_time_ = millis();
420  this->wait_time_ = wait_time_for_command;
421 }
422 
424  if (this->next_command_queue_length_ <= 0) {
425  ESP_LOGE(TAG, "Tried to dequeue command from empty queue");
426  this->next_command_ = EZO_PMP_COMMAND_NONE;
427  this->next_command_volume_ = 0;
428  this->next_command_duration_ = 0;
429  return;
430  }
431 
432  // Read from Head
436 
437  // Move positions
439  if (next_command_queue_head_ >= 10) {
441  }
442 
444 }
445 
447  if (this->next_command_queue_length_ <= 0) {
448  return EZO_PMP_COMMAND_NONE;
449  }
450 
451  return this->next_command_queue_[this->next_command_queue_head_];
452 }
453 
454 void EzoPMP::queue_command_(uint16_t command, double volume, int duration, bool should_schedule) {
455  if (!should_schedule) {
456  return;
457  }
458 
459  if (this->next_command_queue_length_ >= 10) {
460  ESP_LOGE(TAG, "Tried to queue command '%d' but queue is full", command);
461  return;
462  }
463 
464  this->next_command_queue_[this->next_command_queue_last_] = command;
467 
468  ESP_LOGV(TAG, "Queue command '%d' in position '%d'", command, next_command_queue_last_);
469 
470  // Move positions
472  if (next_command_queue_last_ >= 10) {
474  }
475 
477 }
478 
479 // Actions
480 
481 void EzoPMP::find() { this->queue_command_(EZO_PMP_COMMAND_FIND, 0, 0, true); }
482 
484  this->queue_command_(EZO_PMP_COMMAND_DOSE_CONTINUOUSLY, 0, 0, true);
485  this->queue_command_(EZO_PMP_COMMAND_READ_DOSING, 0, 0, true);
486  this->queue_command_(EZO_PMP_COMMAND_READ_SINGLE_REPORT, 0, 0, (bool) this->current_volume_dosed_);
487 }
488 
489 void EzoPMP::dose_volume(double volume) {
490  this->queue_command_(EZO_PMP_COMMAND_DOSE_VOLUME, volume, 0, true);
491  this->queue_command_(EZO_PMP_COMMAND_READ_DOSING, 0, 0, true);
492  this->queue_command_(EZO_PMP_COMMAND_READ_SINGLE_REPORT, 0, 0, (bool) this->current_volume_dosed_);
493 }
494 
495 void EzoPMP::dose_volume_over_time(double volume, int duration) {
496  this->queue_command_(EZO_PMP_COMMAND_DOSE_VOLUME_OVER_TIME, volume, duration, true);
497  this->queue_command_(EZO_PMP_COMMAND_READ_DOSING, 0, 0, true);
498  this->queue_command_(EZO_PMP_COMMAND_READ_SINGLE_REPORT, 0, 0, (bool) this->current_volume_dosed_);
499 }
500 
501 void EzoPMP::dose_with_constant_flow_rate(double volume, int duration) {
502  this->queue_command_(EZO_PMP_COMMAND_DOSE_WITH_CONSTANT_FLOW_RATE, volume, duration, true);
503  this->queue_command_(EZO_PMP_COMMAND_READ_DOSING, 0, 0, true);
504  this->queue_command_(EZO_PMP_COMMAND_READ_SINGLE_REPORT, 0, 0, (bool) this->current_volume_dosed_);
505 }
506 
507 void EzoPMP::set_calibration_volume(double volume) {
508  this->queue_command_(EZO_PMP_COMMAND_SET_CALIBRATION_VOLUME, volume, 0, true);
509  this->queue_command_(EZO_PMP_COMMAND_READ_CALIBRATION_STATUS, 0, 0, true);
510  this->queue_command_(EZO_PMP_COMMAND_READ_MAX_FLOW_RATE, 0, 0, true);
511 }
512 
514  this->queue_command_(EZO_PMP_COMMAND_CLEAR_TOTAL_VOLUME_DOSED, 0, 0, true);
515  this->queue_command_(EZO_PMP_COMMAND_READ_SINGLE_REPORT, 0, 0, true);
516  this->queue_command_(EZO_PMP_COMMAND_READ_TOTAL_VOLUME_DOSED, 0, 0, true);
517  this->queue_command_(EZO_PMP_COMMAND_READ_ABSOLUTE_TOTAL_VOLUME_DOSED, 0, 0, true);
518 }
519 
521  this->queue_command_(EZO_PMP_COMMAND_CLEAR_CALIBRATION, 0, 0, true);
522  this->queue_command_(EZO_PMP_COMMAND_READ_CALIBRATION_STATUS, 0, 0, true);
523  this->queue_command_(EZO_PMP_COMMAND_READ_MAX_FLOW_RATE, 0, 0, true);
524 }
525 
527  this->queue_command_(EZO_PMP_COMMAND_PAUSE_DOSING, 0, 0, true);
528  this->queue_command_(EZO_PMP_COMMAND_READ_PAUSE_STATUS, 0, 0, true);
529 }
530 
531 void EzoPMP::stop_dosing() { this->queue_command_(EZO_PMP_COMMAND_STOP_DOSING, 0, 0, true); }
532 
534  this->queue_command_(EZO_PMP_COMMAND_CHANGE_I2C_ADDRESS, 0, address, true);
535 }
536 
537 void EzoPMP::exec_arbitrary_command(const std::basic_string<char> &command) {
538  this->arbitrary_command_ = command.c_str();
539  this->queue_command_(EZO_PMP_COMMAND_EXEC_ARBITRARY_COMMAND_ADDRESS, 0, 0, true);
540 }
541 
542 } // namespace ezo_pmp
543 } // namespace esphome
uint16_t peek_next_command_()
Definition: ezo_pmp.cpp:446
double next_command_volume_queue_[10]
Definition: ezo_pmp.h:79
sensor::Sensor * absolute_total_volume_dosed_
Definition: ezo_pmp.h:101
int next_command_duration_queue_[10]
Definition: ezo_pmp.h:80
bool is_failed() const
Definition: component.cpp:143
uint16_t current_command_
Definition: ezo_pmp.h:85
optional< std::array< uint8_t, N > > read_bytes_raw()
Definition: i2c.h:225
sensor::Sensor * last_volume_requested_
Definition: ezo_pmp.h:104
void update() override
Definition: ezo_pmp.cpp:49
void change_i2c_address(int address)
Definition: ezo_pmp.cpp:533
text_sensor::TextSensor * dosing_mode_
Definition: ezo_pmp.h:113
binary_sensor::BinarySensor * is_paused_
Definition: ezo_pmp.h:109
void publish_state(const std::string &state)
Definition: text_sensor.cpp:9
sensor::Sensor * total_volume_dosed_
Definition: ezo_pmp.h:100
const char * arbitrary_command_
Definition: ezo_pmp.h:89
void exec_arbitrary_command(const std::basic_string< char > &command)
Definition: ezo_pmp.cpp:537
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
ErrorCode write(const uint8_t *data, size_t len, bool stop=true)
writes an array of bytes to a device using an I2CBus
Definition: i2c.h:186
text_sensor::TextSensor * calibration_status_
Definition: ezo_pmp.h:114
void queue_command_(uint16_t command, double volume, int duration, bool should_schedule)
Definition: ezo_pmp.cpp:454
uint16_t next_command_
Definition: ezo_pmp.h:74
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
void publish_state(bool state)
Publish a new state to the front-end.
void dose_volume_over_time(double volume, int duration)
Definition: ezo_pmp.cpp:495
void dose_volume(double volume)
Definition: ezo_pmp.cpp:489
void dose_with_constant_flow_rate(double volume, int duration)
Definition: ezo_pmp.cpp:501
sensor::Sensor * pump_voltage_
Definition: ezo_pmp.h:102
void set_calibration_volume(double volume)
Definition: ezo_pmp.cpp:507
uint16_t next_command_queue_[10]
Definition: ezo_pmp.h:78
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
uint8_t address
Definition: bl0906.h:211
sensor::Sensor * current_volume_dosed_
Definition: ezo_pmp.h:99
binary_sensor::BinarySensor * is_dosing_
Definition: ezo_pmp.h:108
void loop() override
Definition: ezo_pmp.cpp:81
void dump_config() override
Definition: ezo_pmp.cpp:41
sensor::Sensor * max_flow_rate_
Definition: ezo_pmp.h:103
double next_command_volume_
Definition: ezo_pmp.h:75