10static const char *
const TAG =
"sgp4x";
14 uint16_t raw_serial_number[3];
15 if (!this->
get_register(SGP4X_CMD_GET_SERIAL_ID, raw_serial_number, 3, 1)) {
16 ESP_LOGE(TAG,
"Get serial number failed");
17 this->error_code_ = SERIAL_NUMBER_IDENTIFICATION_FAILED;
21 this->
serial_number_ = (uint64_t(raw_serial_number[0]) << 24) | (uint64_t(raw_serial_number[1]) << 16) |
22 (uint64_t(raw_serial_number[2]));
27 if (!this->
get_register(SGP4X_CMD_GET_FEATURESET, featureset, 1)) {
28 ESP_LOGD(TAG,
"Get feature set failed");
33 if (featureset == SGP40_FEATURESET) {
38 ESP_LOGE(TAG,
"SGP41 required for NOx, disabling NOx sensor");
43 }
else if (featureset == SGP41_FEATURESET) {
48 ESP_LOGD(TAG,
"Unknown feature set 0x%0X", featureset);
53 ESP_LOGD(TAG,
"Version 0x%0X", featureset);
62 if (this->
pref_.
load(&this->voc_baselines_storage_)) {
65 ESP_LOGV(TAG,
"Loaded VOC baseline state0: 0x%04" PRIX32
", state1: 0x%04" PRIX32,
73 ESP_LOGV(TAG,
"Setting VOC baseline from save state0: 0x%04" PRIX32
", state1: 0x%04" PRIX32,
105 ESP_LOGV(TAG,
"Component requires sampling of 1Hz, setting up background sampler");
110 ESP_LOGD(TAG,
"Starting self-test");
112 this->error_code_ = COMMUNICATION_FAILED;
113 ESP_LOGD(TAG, ESP_LOG_MSG_COMM_FAIL);
119 if (!this->
read_data(reply) || (reply != 0xD400)) {
120 this->error_code_ = SELF_TEST_FAILED;
121 ESP_LOGW(TAG,
"Self-test failed (0x%X)", reply);
128 ESP_LOGD(TAG,
"Self-test complete");
147 if (this->
pref_.
save(&this->voc_baselines_storage_)) {
148 ESP_LOGV(TAG,
"Stored VOC baseline state0: 0x%04" PRIX32
", state1: 0x%04" PRIX32,
151 ESP_LOGW(TAG,
"Storing VOC baselines failed");
158 ESP_LOGD(TAG,
"Stabilizing (%d/%d); VOC index: %" PRIu32, this->
samples_read_, this->samples_to_stabilize_,
164 float humidity = NAN;
167 ESP_LOGW(TAG,
"Self-test incomplete");
173 if (std::isnan(humidity) || humidity < 0.0f || humidity > 100.0f) {
187 size_t response_words;
190 command = SGP40_CMD_MEASURE_RAW;
195 command = SGP41_CMD_NOX_CONDITIONING;
199 command = SGP41_CMD_MEASURE_RAW;
203 uint16_t rhticks = (uint16_t) llround((humidity * 65535) / 100);
204 uint16_t tempticks = (uint16_t) (((
temperature + 45) * 65535) / 175);
211 ESP_LOGD(TAG,
"write error (%d)", this->
last_error_);
217 uint16_t raw_data[2];
219 if (!this->
read_data(raw_data, response_words)) {
220 ESP_LOGD(TAG,
"read error (%d)", this->
last_error_);
254 ESP_LOGCONFIG(TAG,
"SGP4x:");
255 LOG_I2C_DEVICE(
this);
256 ESP_LOGCONFIG(TAG,
" Store baseline: %s", YESNO(this->
store_baseline_));
259 switch (this->error_code_) {
260 case COMMUNICATION_FAILED:
261 ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL);
263 case SERIAL_NUMBER_IDENTIFICATION_FAILED:
264 ESP_LOGW(TAG,
"Get serial number failed");
266 case SELF_TEST_FAILED:
267 ESP_LOGW(TAG,
"Self-test failed");
270 ESP_LOGW(TAG,
"Unknown error");
276 " Serial number: %" PRIu64
"\n"
277 " Minimum Samples: %f",
280 LOG_UPDATE_INTERVAL(
this);
282 ESP_LOGCONFIG(TAG,
" Compensation:");
287 ESP_LOGCONFIG(TAG,
" No source configured");
uint32_t get_config_version_hash()
Get the config hash extended with ESPHome version.
void mark_failed()
Mark this component as failed.
void status_set_warning(const char *message=nullptr)
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(const std voi set_timeout)(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_interval(const std voi set_interval)(const char *name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
void status_clear_warning()
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
i2c::ErrorCode last_error_
last error code from I2C operation
bool get_register(uint16_t command, uint16_t *data, uint8_t len, uint8_t delay=0)
get data words from I2C register.
bool write_command(T i2c_register)
Write a command to the I2C device.
bool read_data(uint16_t *data, uint8_t len)
Read data words from I2C device.
void publish_state(float state)
Publish a new state to the front-end.
float state
This member variable stores the last state that has passed through all filters.
SGP4xBaselines voc_baselines_storage_
optional< uint32_t > nox_conditioning_start_
uint32_t seconds_since_last_store_
ESPPreferenceObject pref_
uint8_t samples_to_stabilize_
void dump_config() override
sensor::Sensor * humidity_sensor_
Input sensor for humidity and temperature compensation.
sensor::Sensor * voc_sensor_
VOCGasIndexAlgorithm voc_algorithm_
sensor::Sensor * temperature_sensor_
optional< GasTuning > voc_tuning_params_
NOxGasIndexAlgorithm nox_algorithm_
void update_gas_indices_()
optional< GasTuning > nox_tuning_params_
sensor::Sensor * nox_sensor_
const uint32_t SHORTEST_BASELINE_STORE_INTERVAL
const float MAXIMUM_STORAGE_DIFF
Providing packet encoding functions for exchanging data with a remote host.
constexpr uint32_t fnv1a_hash_extend(uint32_t hash, const char *str)
Extend a FNV-1a hash with additional string data.
ESPPreferences * global_preferences
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.