ESPHome 2025.5.0
Loading...
Searching...
No Matches
ezo.cpp
Go to the documentation of this file.
1#include "ezo.h"
2#include "esphome/core/log.h"
3#include "esphome/core/hal.h"
4
5namespace esphome {
6namespace ezo {
7
8static const char *const EZO_COMMAND_TYPE_STRINGS[] = {"EZO_READ", "EZO_LED", "EZO_DEVICE_INFORMATION",
9 "EZO_SLOPE", "EZO_CALIBRATION", "EZO_SLEEP",
10 "EZO_I2C", "EZO_T", "EZO_CUSTOM"};
11
12static const char *const EZO_CALIBRATION_TYPE_STRINGS[] = {"LOW", "MID", "HIGH"};
13
15 LOG_SENSOR("", "EZO", this);
16 LOG_I2C_DEVICE(this);
17 if (this->is_failed()) {
18 ESP_LOGE(TAG, "Communication with EZO circuit failed!");
19 }
20 LOG_UPDATE_INTERVAL(this);
21}
22
24 // Check if a read is in there already and if not insert on in the second position
25
26 if (!this->commands_.empty() && this->commands_.front()->command_type != EzoCommandType::EZO_READ &&
27 this->commands_.size() > 1) {
28 bool found = false;
29
30 for (auto &i : this->commands_) {
31 if (i->command_type == EzoCommandType::EZO_READ) {
32 found = true;
33 break;
34 }
35 }
36
37 if (!found) {
38 std::unique_ptr<EzoCommand> ezo_command(new EzoCommand);
39 ezo_command->command = "R";
40 ezo_command->command_type = EzoCommandType::EZO_READ;
41 ezo_command->delay_ms = 900;
42
43 auto it = this->commands_.begin();
44 ++it;
45 this->commands_.insert(it, std::move(ezo_command));
46 }
47
48 return;
49 }
50
51 this->get_state();
52}
53
55 if (this->commands_.empty()) {
56 return;
57 }
58
59 EzoCommand *to_run = this->commands_.front().get();
60
61 if (!to_run->command_sent) {
62 const uint8_t *data = reinterpret_cast<const uint8_t *>(to_run->command.c_str());
63 ESP_LOGVV(TAG, "Sending command \"%s\"", data);
64
65 this->write(data, to_run->command.length());
66
68 to_run->command_type == EzoCommandType::EZO_I2C) { // Commands with no return data
69 this->commands_.pop_front();
71 this->address_ = this->new_address_;
72 return;
73 }
74
75 this->start_time_ = millis();
76 to_run->command_sent = true;
77 return;
78 }
79
80 if (millis() - this->start_time_ < to_run->delay_ms)
81 return;
82
83 uint8_t buf[32];
84
85 buf[0] = 0;
86
87 if (!this->read_bytes_raw(buf, 32)) {
88 ESP_LOGE(TAG, "read error");
89 this->commands_.pop_front();
90 return;
91 }
92
93 switch (buf[0]) {
94 case 1:
95 break;
96 case 2:
97 ESP_LOGE(TAG, "device returned a syntax error");
98 break;
99 case 254:
100 return; // keep waiting
101 case 255:
102 ESP_LOGE(TAG, "device returned no data");
103 break;
104 default:
105 ESP_LOGE(TAG, "device returned an unknown response: %d", buf[0]);
106 break;
107 }
108
109 ESP_LOGV(TAG, "Received buffer \"%s\" for command type %s", &buf[1], EZO_COMMAND_TYPE_STRINGS[to_run->command_type]);
110
111 if (buf[0] == 1) {
112 std::string payload = reinterpret_cast<char *>(&buf[1]);
113 if (!payload.empty()) {
114 auto start_location = payload.find(',');
115 switch (to_run->command_type) {
117 // some sensors return multiple comma-separated values, terminate string after first one
118 if (start_location != std::string::npos) {
119 payload.erase(start_location);
120 }
121 auto val = parse_number<float>(payload);
122 if (!val.has_value()) {
123 ESP_LOGW(TAG, "Can't convert '%s' to number!", payload.c_str());
124 } else {
125 this->publish_state(*val);
126 }
127 break;
128 }
130 this->led_callback_.call(payload.back() == '1');
131 break;
133 if (start_location != std::string::npos) {
134 this->device_infomation_callback_.call(payload.substr(start_location + 1));
135 }
136 break;
138 if (start_location != std::string::npos) {
139 this->slope_callback_.call(payload.substr(start_location + 1));
140 }
141 break;
143 if (start_location != std::string::npos) {
144 this->calibration_callback_.call(payload.substr(start_location + 1));
145 }
146 break;
148 if (start_location != std::string::npos) {
149 this->t_callback_.call(payload.substr(start_location + 1));
150 }
151 break;
153 this->custom_callback_.call(payload);
154 break;
155 default:
156 break;
157 }
158 }
159 }
160 this->commands_.pop_front();
161}
162
163void EZOSensor::add_command_(const std::string &command, EzoCommandType command_type, uint16_t delay_ms) {
164 std::unique_ptr<EzoCommand> ezo_command(new EzoCommand);
165 ezo_command->command = command;
166 ezo_command->command_type = command_type;
167 ezo_command->delay_ms = delay_ms;
168 this->commands_.push_back(std::move(ezo_command));
169}
170
172 std::string payload = str_sprintf("Cal,%s,%0.2f", EZO_CALIBRATION_TYPE_STRINGS[type], value);
174}
175
177 if (address > 0 && address < 128) {
178 std::string payload = str_sprintf("I2C,%u", address);
179 this->new_address_ = address;
181 } else {
182 ESP_LOGE(TAG, "Invalid I2C address");
183 }
184}
185
187
189
191
193
195
196void EZOSensor::set_t(float value) {
197 std::string payload = str_sprintf("T,%0.2f", value);
198 this->add_command_(payload, EzoCommandType::EZO_T);
199}
200
201void EZOSensor::set_tempcomp_value(float temp) { this->set_t(temp); }
202
204
208
212
216
218 std::string payload = str_sprintf("Cal,%0.2f", value);
220}
221
223
225
227 std::string to_send = "L,";
228 to_send += on ? "1" : "0";
230}
231
232void EZOSensor::send_custom(const std::string &to_send) { this->add_command_(to_send, EzoCommandType::EZO_CUSTOM); }
233
234} // namespace ezo
235} // namespace esphome
uint8_t address
Definition bl0906.h:4
bool is_failed() const
void set_led_state(bool on)
Definition ezo.cpp:226
void set_address(uint8_t address)
Definition ezo.cpp:176
CallbackManager< void(std::string)> calibration_callback_
Definition ezo.h:101
void loop() override
Definition ezo.cpp:54
void set_calibration_point_mid(float value)
Definition ezo.cpp:209
void set_calibration_point_high(float value)
Definition ezo.cpp:213
void set_calibration_point_low(float value)
Definition ezo.cpp:205
void set_t(float value)
Definition ezo.cpp:196
CallbackManager< void(bool)> led_callback_
Definition ezo.h:105
void set_calibration_generic(float value)
Definition ezo.cpp:217
void set_tempcomp_value(float temp)
Definition ezo.cpp:201
void update() override
Definition ezo.cpp:23
void get_device_information()
Definition ezo.cpp:186
CallbackManager< void(std::string)> device_infomation_callback_
Definition ezo.h:100
uint32_t start_time_
Definition ezo.h:107
CallbackManager< void(std::string)> t_callback_
Definition ezo.h:103
void set_calibration_point_(EzoCalibrationType type, float value)
Definition ezo.cpp:171
CallbackManager< void(std::string)> slope_callback_
Definition ezo.h:102
std::deque< std::unique_ptr< EzoCommand > > commands_
Definition ezo.h:93
void send_custom(const std::string &to_send)
Definition ezo.cpp:232
void add_command_(const std::string &command, EzoCommandType command_type, uint16_t delay_ms=300)
Definition ezo.cpp:163
CallbackManager< void(std::string)> custom_callback_
Definition ezo.h:104
void dump_config() override
Definition ezo.cpp:14
EzoCommandType command_type
Definition ezo.h:32
std::string command
Definition ezo.h:29
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:190
optional< std::array< uint8_t, N > > read_bytes_raw()
Definition i2c.h:229
uint8_t address_
store the address of the device on the bus
Definition i2c.h:273
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:39
uint8_t type
mopeka_std_values val[4]
EzoCalibrationType
Definition ezo.h:25
@ EZO_CAL_MID
Definition ezo.h:25
@ EZO_CAL_HIGH
Definition ezo.h:25
@ EZO_CAL_LOW
Definition ezo.h:25
EzoCommandType
Definition ezo.h:13
@ EZO_SLOPE
Definition ezo.h:17
@ EZO_READ
Definition ezo.h:14
@ EZO_LED
Definition ezo.h:15
@ EZO_CUSTOM
Definition ezo.h:22
@ EZO_DEVICE_INFORMATION
Definition ezo.h:16
@ EZO_SLEEP
Definition ezo.h:19
@ EZO_CALIBRATION
Definition ezo.h:18
@ EZO_T
Definition ezo.h:21
@ EZO_I2C
Definition ezo.h:20
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
optional< T > parse_number(const char *str)
Parse an unsigned decimal number from a null-terminated string.
Definition helpers.h:313
std::string str_sprintf(const char *fmt,...)
Definition helpers.cpp:323
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:27