68 " BSEC2 version: %d.%d.%d.%d\n"
69 " BSEC2 configuration blob:\n"
71 this->
version_.major, this->version_.minor, this->version_.major_bugfix, this->version_.minor_bugfix,
78 ESP_LOGE(TAG,
"Communication failed (BSEC2 status: %d, BME68X status: %d)", this->
bsec_status_,
80 if (this->
bsec_status_ == BSEC_I_SU_SUBSCRIBEDOUTPUTGATES) {
81 ESP_LOGE(TAG,
"No sensors, add at least one sensor to the config");
86 ESP_LOGCONFIG(TAG,
" Algorithm output: %s", BME68X_BSEC2_ALGORITHM_OUTPUT_LOG(this->
algorithm_output_));
89 " Operating age: %s\n"
92 " State save interval: %" PRIu32
"ms\n"
93 " Temperature offset: %.2f",
111#ifdef USE_TEXT_SENSOR
160 bsec_sensor_configuration_t virtual_sensors[BSEC_NUMBER_OUTPUTS];
161 uint8_t num_virtual_sensors = 0;
164 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_IAQ;
166 num_virtual_sensors++;
170 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_STATIC_IAQ;
172 num_virtual_sensors++;
176 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_CO2_EQUIVALENT;
178 num_virtual_sensors++;
182 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_BREATH_VOC_EQUIVALENT;
184 num_virtual_sensors++;
188 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_PRESSURE;
190 num_virtual_sensors++;
194 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_GAS;
196 num_virtual_sensors++;
200 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE;
202 num_virtual_sensors++;
206 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY;
208 num_virtual_sensors++;
211 bsec_sensor_configuration_t sensor_settings[BSEC_MAX_PHYSICAL_SENSOR];
212 uint8_t num_sensor_settings = BSEC_MAX_PHYSICAL_SENSOR;
214 sensor_settings, &num_sensor_settings);
223 ESP_LOGV(TAG,
"Performing sensor run");
225 struct bme68x_conf bme68x_conf;
227 if (this->bsec_status_ < BSEC_OK) {
228 ESP_LOGW(TAG,
"Fetching control settings failed (BSEC2 error code %d)", this->bsec_status_);
233 case BME68X_FORCED_MODE:
234 bme68x_get_conf(&bme68x_conf, &this->
bme68x_);
237 bme68x_conf.os_temp = this->
bsec_settings_.temperature_oversampling;
239 bme68x_set_conf(&bme68x_conf, &this->
bme68x_);
247 this->
op_mode_ = BME68X_FORCED_MODE;
248 ESP_LOGV(TAG,
"Using forced mode");
251 case BME68X_PARALLEL_MODE:
253 bme68x_get_conf(&bme68x_conf, &this->
bme68x_);
256 bme68x_conf.os_temp = this->
bsec_settings_.temperature_oversampling;
258 bme68x_set_conf(&bme68x_conf, &this->
bme68x_);
265 BSEC_TOTAL_HEAT_DUR -
266 (bme68x_get_meas_dur(BME68X_PARALLEL_MODE, &bme68x_conf, &this->
bme68x_) / INT64_C(1000));
269 this->bme68x_status_ = bme68x_set_op_mode(BME68X_PARALLEL_MODE, &this->
bme68x_);
270 this->
op_mode_ = BME68X_PARALLEL_MODE;
271 ESP_LOGV(TAG,
"Using parallel mode");
274 case BME68X_SLEEP_MODE:
276 bme68x_set_op_mode(BME68X_SLEEP_MODE, &this->
bme68x_);
278 ESP_LOGV(TAG,
"Using sleep mode");
283 if (this->
bsec_settings_.trigger_measurement && this->bsec_settings_.op_mode != BME68X_SLEEP_MODE) {
284 bme68x_get_conf(&bme68x_conf, &this->
bme68x_);
286 ESP_LOGV(TAG,
"Queueing read in %" PRIu32
"us", meas_dur);
290 ESP_LOGV(TAG,
"Measurement not required, queueing immediate read");
297 ESP_LOGV(TAG,
"Reading data");
300 ESP_LOGV(TAG,
"Data processing not required");
304 struct bme68x_data data[3];
309 ESP_LOGV(TAG,
"BME68X did not provide new data");
313 ESP_LOGW(TAG,
"Fetching data failed (BME68X error code %d)", this->
bme68x_status_);
317 ESP_LOGV(TAG,
"BME68X did not provide new fields");
321 for (uint8_t i = 0; i < nFields; i++) {
322 bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR];
323 uint8_t num_inputs = 0;
325 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_TEMPERATURE)) {
326 inputs[num_inputs].sensor_id = BSEC_INPUT_TEMPERATURE;
327 inputs[num_inputs].signal = data[i].temperature;
328 inputs[num_inputs].time_stamp = trigger_time_ns;
331 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_HEATSOURCE)) {
332 inputs[num_inputs].sensor_id = BSEC_INPUT_HEATSOURCE;
334 inputs[num_inputs].time_stamp = trigger_time_ns;
337 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_HUMIDITY)) {
338 inputs[num_inputs].sensor_id = BSEC_INPUT_HUMIDITY;
339 inputs[num_inputs].signal = data[i].humidity;
340 inputs[num_inputs].time_stamp = trigger_time_ns;
343 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_PRESSURE)) {
344 inputs[num_inputs].sensor_id = BSEC_INPUT_PRESSURE;
345 inputs[num_inputs].signal = data[i].pressure;
346 inputs[num_inputs].time_stamp = trigger_time_ns;
349 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_GASRESISTOR)) {
350 if (data[i].
status & BME68X_GASM_VALID_MSK) {
351 inputs[num_inputs].sensor_id = BSEC_INPUT_GASRESISTOR;
352 inputs[num_inputs].signal = data[i].gas_resistance;
353 inputs[num_inputs].time_stamp = trigger_time_ns;
356 ESP_LOGD(TAG,
"BME68X did not report gas data");
359 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_PROFILE_PART) &&
360 (data[i].status & BME68X_GASM_VALID_MSK)) {
361 inputs[num_inputs].sensor_id = BSEC_INPUT_PROFILE_PART;
362 inputs[num_inputs].signal = (this->
op_mode_ == BME68X_FORCED_MODE) ? 0 : data[i].gas_index;
363 inputs[num_inputs].time_stamp = trigger_time_ns;
367 if (num_inputs < 1) {
368 ESP_LOGD(TAG,
"No signal inputs available for BSEC2");
372 bsec_output_t outputs[BSEC_NUMBER_OUTPUTS];
373 uint8_t num_outputs = BSEC_NUMBER_OUTPUTS;
376 ESP_LOGW(TAG,
"Signal processing failed (BSEC2 error code %d)", this->
bsec_status_);
379 if (num_outputs < 1) {
380 ESP_LOGD(TAG,
"No signal outputs provided by BSEC2");
384 this->
publish_(outputs, num_outputs);
389 ESP_LOGV(TAG,
"Publishing sensor states");
390 bool update_accuracy =
false;
391 uint8_t max_accuracy = 0;
392 for (uint8_t i = 0; i < num_outputs; i++) {
393 float signal = outputs[i].signal;
394 switch (outputs[i].sensor_id) {
395 case BSEC_OUTPUT_IAQ:
396 max_accuracy = std::max(outputs[i].accuracy, max_accuracy);
397 update_accuracy =
true;
402 case BSEC_OUTPUT_STATIC_IAQ:
403 max_accuracy = std::max(outputs[i].accuracy, max_accuracy);
404 update_accuracy =
true;
409 case BSEC_OUTPUT_CO2_EQUIVALENT:
414 case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
419 case BSEC_OUTPUT_RAW_PRESSURE:
424 case BSEC_OUTPUT_RAW_GAS:
429 case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
434 case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
441 if (update_accuracy) {
442 max_accuracy = std::min<uint8_t>(max_accuracy, std::size(IAQ_ACCURACY_STATES) - 1);
447#ifdef USE_TEXT_SENSOR
507 ESP_LOGV(TAG,
"Saving state");
509 uint8_t
state[BSEC_MAX_STATE_BLOB_SIZE];
510 uint8_t work_buffer[BSEC_MAX_STATE_BLOB_SIZE];
511 uint32_t num_serialized_state = BSEC_MAX_STATE_BLOB_SIZE;
514 BSEC_MAX_STATE_BLOB_SIZE, &num_serialized_state);
516 ESP_LOGW(TAG,
"Failed fetch state for save (BSEC2 error code %d)", this->
bsec_status_);
521 ESP_LOGW(TAG,
"Failed to save state");
526 ESP_LOGI(TAG,
"Saved state");