61 " BSEC2 version: %d.%d.%d.%d\n"
62 " BSEC2 configuration blob:\n"
64 this->
version_.major, this->version_.minor, this->version_.major_bugfix, this->version_.minor_bugfix,
71 ESP_LOGE(TAG,
"Communication failed (BSEC2 status: %d, BME68X status: %d)", this->
bsec_status_,
73 if (this->
bsec_status_ == BSEC_I_SU_SUBSCRIBEDOUTPUTGATES) {
74 ESP_LOGE(TAG,
"No sensors, add at least one sensor to the config");
79 ESP_LOGCONFIG(TAG,
" Algorithm output: %s", BME68X_BSEC2_ALGORITHM_OUTPUT_LOG(this->
algorithm_output_));
82 " Operating age: %s\n"
85 " State save interval: %ims\n"
86 " Temperature offset: %.2f",
104#ifdef USE_TEXT_SENSOR
152 bsec_sensor_configuration_t virtual_sensors[BSEC_NUMBER_OUTPUTS];
153 uint8_t num_virtual_sensors = 0;
156 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_IAQ;
158 num_virtual_sensors++;
162 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_STATIC_IAQ;
164 num_virtual_sensors++;
168 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_CO2_EQUIVALENT;
170 num_virtual_sensors++;
174 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_BREATH_VOC_EQUIVALENT;
176 num_virtual_sensors++;
180 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_PRESSURE;
182 num_virtual_sensors++;
186 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_GAS;
188 num_virtual_sensors++;
192 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE;
194 num_virtual_sensors++;
198 virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY;
200 num_virtual_sensors++;
203 bsec_sensor_configuration_t sensor_settings[BSEC_MAX_PHYSICAL_SENSOR];
204 uint8_t num_sensor_settings = BSEC_MAX_PHYSICAL_SENSOR;
206 sensor_settings, &num_sensor_settings);
217 ESP_LOGV(TAG,
"Performing sensor run");
219 struct bme68x_conf bme68x_conf;
221 if (this->bsec_status_ < BSEC_OK) {
222 ESP_LOGW(TAG,
"Failed to fetch sensor control settings (BSEC2 error code %d)", this->bsec_status_);
227 case BME68X_FORCED_MODE:
228 bme68x_get_conf(&bme68x_conf, &this->
bme68x_);
231 bme68x_conf.os_temp = this->
bsec_settings_.temperature_oversampling;
233 bme68x_set_conf(&bme68x_conf, &this->
bme68x_);
240 status = bme68x_set_op_mode(BME68X_FORCED_MODE, &this->
bme68x_);
241 this->
op_mode_ = BME68X_FORCED_MODE;
242 ESP_LOGV(TAG,
"Using forced mode");
245 case BME68X_PARALLEL_MODE:
247 bme68x_get_conf(&bme68x_conf, &this->
bme68x_);
250 bme68x_conf.os_temp = this->
bsec_settings_.temperature_oversampling;
252 bme68x_set_conf(&bme68x_conf, &this->
bme68x_);
259 BSEC_TOTAL_HEAT_DUR -
260 (bme68x_get_meas_dur(BME68X_PARALLEL_MODE, &bme68x_conf, &this->
bme68x_) / INT64_C(1000));
264 status = bme68x_set_op_mode(BME68X_PARALLEL_MODE, &this->
bme68x_);
265 this->
op_mode_ = BME68X_PARALLEL_MODE;
266 ESP_LOGV(TAG,
"Using parallel mode");
269 case BME68X_SLEEP_MODE:
271 bme68x_set_op_mode(BME68X_SLEEP_MODE, &this->
bme68x_);
273 ESP_LOGV(TAG,
"Using sleep mode");
278 if (this->
bsec_settings_.trigger_measurement && this->bsec_settings_.op_mode != BME68X_SLEEP_MODE) {
279 uint32_t meas_dur = 0;
280 meas_dur = bme68x_get_meas_dur(this->
op_mode_, &bme68x_conf, &this->
bme68x_);
281 ESP_LOGV(TAG,
"Queueing read in %uus", meas_dur);
282 this->
set_timeout(
"read", meas_dur / 1000, [
this, curr_time_ns]() { this->
read_(curr_time_ns); });
284 ESP_LOGV(TAG,
"Measurement not required");
285 this->
read_(curr_time_ns);
290 ESP_LOGV(TAG,
"Reading data");
293 uint8_t current_op_mode;
296 if (current_op_mode == BME68X_SLEEP_MODE) {
297 ESP_LOGV(TAG,
"Still in sleep mode, doing nothing");
303 ESP_LOGV(TAG,
"Data processing not required");
307 struct bme68x_data data[3];
312 ESP_LOGW(TAG,
"Failed to get sensor data (BME68X error code %d)", this->
bme68x_status_);
316 ESP_LOGD(TAG,
"BME68X did not provide new data");
320 for (uint8_t i = 0; i < nFields; i++) {
321 bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR];
322 uint8_t num_inputs = 0;
324 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_TEMPERATURE)) {
325 inputs[num_inputs].sensor_id = BSEC_INPUT_TEMPERATURE;
326 inputs[num_inputs].signal = data[i].temperature;
327 inputs[num_inputs].time_stamp = trigger_time_ns;
330 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_HEATSOURCE)) {
331 inputs[num_inputs].sensor_id = BSEC_INPUT_HEATSOURCE;
333 inputs[num_inputs].time_stamp = trigger_time_ns;
336 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_HUMIDITY)) {
337 inputs[num_inputs].sensor_id = BSEC_INPUT_HUMIDITY;
338 inputs[num_inputs].signal = data[i].humidity;
339 inputs[num_inputs].time_stamp = trigger_time_ns;
342 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_PRESSURE)) {
343 inputs[num_inputs].sensor_id = BSEC_INPUT_PRESSURE;
344 inputs[num_inputs].signal = data[i].pressure;
345 inputs[num_inputs].time_stamp = trigger_time_ns;
348 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_GASRESISTOR)) {
349 if (data[i].
status & BME68X_GASM_VALID_MSK) {
350 inputs[num_inputs].sensor_id = BSEC_INPUT_GASRESISTOR;
351 inputs[num_inputs].signal = data[i].gas_resistance;
352 inputs[num_inputs].time_stamp = trigger_time_ns;
355 ESP_LOGD(TAG,
"BME68X did not report gas data");
358 if (BSEC_CHECK_INPUT(this->
bsec_settings_.process_data, BSEC_INPUT_PROFILE_PART) &&
359 (data[i].status & BME68X_GASM_VALID_MSK)) {
360 inputs[num_inputs].sensor_id = BSEC_INPUT_PROFILE_PART;
361 inputs[num_inputs].signal = (this->
op_mode_ == BME68X_FORCED_MODE) ? 0 : data[i].gas_index;
362 inputs[num_inputs].time_stamp = trigger_time_ns;
366 if (num_inputs < 1) {
367 ESP_LOGD(TAG,
"No signal inputs available for BSEC2");
371 bsec_output_t outputs[BSEC_NUMBER_OUTPUTS];
372 uint8_t num_outputs = BSEC_NUMBER_OUTPUTS;
375 ESP_LOGW(TAG,
"BSEC2 failed to process signals (BSEC2 error code %d)", this->
bsec_status_);
378 if (num_outputs < 1) {
379 ESP_LOGD(TAG,
"No signal outputs provided by BSEC2");
383 this->
publish_(outputs, num_outputs);
388 ESP_LOGV(TAG,
"Publishing sensor states");
389 bool update_accuracy =
false;
390 uint8_t max_accuracy = 0;
391 for (uint8_t i = 0; i < num_outputs; i++) {
392 float signal = outputs[i].signal;
393 switch (outputs[i].sensor_id) {
394 case BSEC_OUTPUT_IAQ:
395 max_accuracy = std::max(outputs[i].accuracy, max_accuracy);
396 update_accuracy =
true;
401 case BSEC_OUTPUT_STATIC_IAQ:
402 max_accuracy = std::max(outputs[i].accuracy, max_accuracy);
403 update_accuracy =
true;
408 case BSEC_OUTPUT_CO2_EQUIVALENT:
413 case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
418 case BSEC_OUTPUT_RAW_PRESSURE:
423 case BSEC_OUTPUT_RAW_GAS:
428 case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
433 case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
440 if (update_accuracy) {
445#ifdef USE_TEXT_SENSOR
505 ESP_LOGV(TAG,
"Saving state");
507 uint8_t
state[BSEC_MAX_STATE_BLOB_SIZE];
508 uint8_t work_buffer[BSEC_MAX_STATE_BLOB_SIZE];
509 uint32_t num_serialized_state = BSEC_MAX_STATE_BLOB_SIZE;
512 BSEC_MAX_STATE_BLOB_SIZE, &num_serialized_state);
514 ESP_LOGW(TAG,
"Failed fetch state for save (BSEC2 error code %d)", this->
bsec_status_);
519 ESP_LOGW(TAG,
"Failed to save state");
524 ESP_LOGI(TAG,
"Saved state");