ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
ags10.cpp
Go to the documentation of this file.
1#include "ags10.h"
3
4#include <cinttypes>
5
6namespace esphome::ags10 {
7ESPHOME_LOG_TAG(TAG, "ags10");
8
9// Data acquisition.
10static const uint8_t REG_TVOC = 0x00;
11// Zero-point calibration.
12static const uint8_t REG_CALIBRATION = 0x01;
13// Read version.
14static const uint8_t REG_VERSION = 0x11;
15// Read current resistance.
16static const uint8_t REG_RESISTANCE = 0x20;
17// Modify target address.
18static const uint8_t REG_ADDRESS = 0x21;
19
20// Zero-point calibration with current resistance.
21static const uint16_t ZP_CURRENT = 0x0000;
22// Zero-point reset.
23static const uint16_t ZP_DEFAULT = 0xFFFF;
24
26 auto version = this->read_version_();
27 if (version) {
28 ESP_LOGD(TAG, "AGS10 Sensor Version: 0x%02X", *version);
29 if (this->version_ != nullptr) {
30 this->version_->publish_state(*version);
31 }
32 } else {
33 ESP_LOGE(TAG, "AGS10 Sensor Version: unknown");
34 }
35
36 auto resistance = this->read_resistance_();
37 if (resistance) {
38 ESP_LOGD(TAG, "AGS10 Sensor Resistance: 0x%08" PRIX32, *resistance);
39 if (this->resistance_ != nullptr) {
40 this->resistance_->publish_state(*resistance);
41 }
42 } else {
43 ESP_LOGE(TAG, "AGS10 Sensor Resistance: unknown");
44 }
45}
46
48 auto tvoc = this->read_tvoc_();
49 if (tvoc) {
50 this->tvoc_->publish_state(*tvoc);
52 } else {
53 this->status_set_warning();
54 }
55}
56
58 ESP_LOGCONFIG(TAG, "AGS10:");
59 LOG_I2C_DEVICE(this);
60 switch (this->error_code_) {
61 case NONE:
62 break;
64 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
65 break;
67 ESP_LOGE(TAG, "The crc check failed");
68 break;
69 case ILLEGAL_STATUS:
70 ESP_LOGE(TAG, "AGS10 is not ready to return TVOC data or sensor in pre-heat stage.");
71 break;
73 ESP_LOGE(TAG, "AGS10 returns TVOC data in unsupported units.");
74 break;
75 default:
76 ESP_LOGE(TAG, "Unknown error: %d", this->error_code_);
77 break;
78 }
79 LOG_UPDATE_INTERVAL(this);
80 LOG_SENSOR(" ", "TVOC Sensor", this->tvoc_);
81 LOG_SENSOR(" ", "Firmware Version Sensor", this->version_);
82 LOG_SENSOR(" ", "Resistance Sensor", this->resistance_);
83}
84
88bool AGS10Component::new_i2c_address(uint8_t newaddress) {
89 uint8_t rev_newaddress = ~newaddress;
90 std::array<uint8_t, 5> data{newaddress, rev_newaddress, newaddress, rev_newaddress, 0};
91 data[4] = crc8(data.data(), 4, 0xFF, 0x31, true);
92 if (!this->write_bytes(REG_ADDRESS, data)) {
93 this->error_code_ = COMMUNICATION_FAILED;
94 this->status_set_warning();
95 ESP_LOGE(TAG, "couldn't write the new I2C address 0x%02X", newaddress);
96 return false;
97 }
98 this->set_i2c_address(newaddress);
99 ESP_LOGW(TAG, "changed I2C address to 0x%02X", newaddress);
100 this->error_code_ = NONE;
101 this->status_clear_warning();
102 return true;
103}
104
106
108
110 switch (mode) {
111 case FACTORY_DEFAULT:
113 break;
114 case CURRENT_VALUE:
116 break;
117 case CUSTOM_VALUE:
118 this->set_zero_point_with(value);
119 break;
120 }
121}
122
124 std::array<uint8_t, 5> data{0x00, 0x0C, (uint8_t) ((value >> 8) & 0xFF), (uint8_t) (value & 0xFF), 0};
125 data[4] = crc8(data.data(), 4, 0xFF, 0x31, true);
126 if (!this->write_bytes(REG_CALIBRATION, data)) {
127 this->error_code_ = COMMUNICATION_FAILED;
128 this->status_set_warning();
129 ESP_LOGE(TAG, "unable to set zero-point calibration with 0x%02X", value);
130 return false;
131 }
132 if (value == ZP_CURRENT) {
133 ESP_LOGI(TAG, "zero-point calibration has been set with current resistance");
134 } else if (value == ZP_DEFAULT) {
135 ESP_LOGI(TAG, "zero-point calibration has been reset to the factory defaults");
136 } else {
137 ESP_LOGI(TAG, "zero-point calibration has been set with 0x%02X", value);
138 }
139 this->error_code_ = NONE;
140 this->status_clear_warning();
141 return true;
142}
143
144optional<uint32_t> AGS10Component::read_tvoc_() {
145 auto data = this->read_and_check_<5>(REG_TVOC);
146 if (!data) {
147 return nullopt;
148 }
149
150 auto res = *data;
151 auto status_byte = res[0];
152
153 int units = status_byte & 0x0e;
154 int status_bit = status_byte & 0x01;
155
156 if (status_bit != 0) {
157 this->error_code_ = ILLEGAL_STATUS;
158 ESP_LOGW(TAG, "Reading AGS10 data failed: illegal status (not ready or sensor in pre-heat stage)!");
159 return nullopt;
160 }
161
162 if (units != 0) {
163 this->error_code_ = UNSUPPORTED_UNITS;
164 ESP_LOGE(TAG, "Reading AGS10 data failed: unsupported units (%d)!", units);
165 return nullopt;
166 }
167
168 return encode_uint24(res[1], res[2], res[3]);
169}
170
171optional<uint8_t> AGS10Component::read_version_() {
172 auto data = this->read_and_check_<5>(REG_VERSION);
173 if (data) {
174 auto res = *data;
175 return res[3];
176 }
177 return nullopt;
178}
179
181 auto data = this->read_and_check_<5>(REG_RESISTANCE);
182 if (data) {
183 auto res = *data;
184 return encode_uint32(res[0], res[1], res[2], res[3]);
185 }
186 return nullopt;
187}
188
189template<size_t N> optional<std::array<uint8_t, N>> AGS10Component::read_and_check_(uint8_t a_register) {
190 auto data = this->read_bytes<N>(a_register);
191 if (!data.has_value()) {
192 this->error_code_ = COMMUNICATION_FAILED;
193 ESP_LOGE(TAG, "Reading AGS10 version failed!");
194 return optional<std::array<uint8_t, N>>();
195 }
196 auto len = N - 1;
197 auto res = *data;
198 auto crc_byte = res[len];
199
200 if (crc_byte != crc8(res.data(), len, 0xFF, 0x31, true)) {
201 this->error_code_ = CRC_CHECK_FAILED;
202 ESP_LOGE(TAG, "Reading AGS10 version failed: crc error!");
203 return optional<std::array<uint8_t, N>>();
204 }
205
206 return data;
207}
208} // namespace esphome::ags10
BedjetMode mode
BedJet operating mode.
void status_clear_warning()
Definition component.h:296
optional< std::array< uint8_t, N > > read_and_check_(uint8_t a_register)
Read, checks and returns data from the sensor.
Definition ags10.cpp:189
bool set_zero_point_with_factory_defaults()
Sets zero-point with factory defaults.
Definition ags10.cpp:105
optional< uint8_t > read_version_()
Reads and returns a firmware version of AGS10.
Definition ags10.cpp:171
enum esphome::ags10::AGS10Component::ErrorCode NONE
sensor::Sensor * tvoc_
TVOC.
Definition ags10.h:72
bool set_zero_point_with_current_resistance()
Sets zero-point with current sensor resistance.
Definition ags10.cpp:107
sensor::Sensor * resistance_
Resistance.
Definition ags10.h:82
optional< uint32_t > read_resistance_()
Reads and returns the resistance of AGS10.
Definition ags10.cpp:180
optional< uint32_t > read_tvoc_()
Reads and returns value of TVOC.
Definition ags10.cpp:144
void set_zero_point(AGS10SetZeroPointActionMode mode, uint16_t value)
Sets zero-point by mode; the value is only used for CUSTOM_VALUE.
Definition ags10.cpp:109
sensor::Sensor * version_
Firmvare version.
Definition ags10.h:77
bool set_zero_point_with(uint16_t value)
Sets zero-point with the value.
Definition ags10.cpp:123
bool new_i2c_address(uint8_t newaddress)
Modifies target address of AGS10.
Definition ags10.cpp:88
void dump_config() override
Definition ags10.cpp:57
void set_i2c_address(uint8_t address)
We store the address of the device on the bus.
Definition i2c.h:151
bool write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len) const
Definition i2c.h:298
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
Definition i2c.h:249
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:65
ESPHOME_LOG_TAG(TAG, "ags10")
AGS10SetZeroPointActionMode
Definition ags10.h:9
@ CURRENT_VALUE
Definition ags10.h:13
@ FACTORY_DEFAULT
Definition ags10.h:11
const void size_t len
Definition hal.h:68
constexpr uint32_t encode_uint24(uint8_t byte1, uint8_t byte2, uint8_t byte3)
Encode a 24-bit value given three bytes in most to least significant byte order.
Definition helpers.h:1002
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
Definition helpers.h:1006
uint8_t crc8(const uint8_t *data, uint8_t len, uint8_t crc, uint8_t poly, bool msb_first)
Calculate a CRC-8 checksum of data with size len.
Definition helpers.cpp:68