BME680 BSEC: Allow sample rate overrides for T/P/H sensors (#1710)

This commit is contained in:
Trevor North 2021-05-23 21:27:19 +01:00 committed by GitHub
parent 063d9c47a4
commit cccb1a2c9e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 141 additions and 98 deletions

View file

@ -60,5 +60,5 @@ def to_code(config):
var.set_state_save_interval(config[CONF_STATE_SAVE_INTERVAL].total_milliseconds) var.set_state_save_interval(config[CONF_STATE_SAVE_INTERVAL].total_milliseconds)
) )
cg.add_define("USING_BSEC") cg.add_define("USE_BSEC")
cg.add_library("BSEC Software Library", "1.6.1480") cg.add_library("BSEC Software Library", "1.6.1480")

View file

@ -1,5 +1,3 @@
#include "bme680_bsec.h" #include "bme680_bsec.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "esphome/core/helpers.h" #include "esphome/core/helpers.h"
@ -7,7 +5,7 @@
namespace esphome { namespace esphome {
namespace bme680_bsec { namespace bme680_bsec {
#ifdef USING_BSEC #ifdef USE_BSEC
static const char *TAG = "bme680_bsec.sensor"; static const char *TAG = "bme680_bsec.sensor";
static const std::string IAQ_ACCURACY_STATES[4] = {"Stabilizing", "Uncertain", "Calibrating", "Calibrated"}; static const std::string IAQ_ACCURACY_STATES[4] = {"Stabilizing", "Uncertain", "Calibrating", "Calibrated"};
@ -30,7 +28,6 @@ void BME680BSECComponent::setup() {
this->bme680_.write = BME680BSECComponent::write_bytes_wrapper; this->bme680_.write = BME680BSECComponent::write_bytes_wrapper;
this->bme680_.delay_ms = BME680BSECComponent::delay_ms; this->bme680_.delay_ms = BME680BSECComponent::delay_ms;
this->bme680_.amb_temp = 25; this->bme680_.amb_temp = 25;
this->bme680_.power_mode = BME680_FORCED_MODE;
this->bme680_status_ = bme680_init(&this->bme680_); this->bme680_status_ = bme680_init(&this->bme680_);
if (this->bme680_status_ != BME680_OK) { if (this->bme680_status_ != BME680_OK) {
@ -43,14 +40,13 @@ void BME680BSECComponent::setup() {
#include "config/generic_33v_300s_28d/bsec_iaq.txt" #include "config/generic_33v_300s_28d/bsec_iaq.txt"
}; };
this->set_config_(bsec_config); this->set_config_(bsec_config);
this->update_subscription_(BSEC_SAMPLE_RATE_ULP);
} else { } else {
const uint8_t bsec_config[] = { const uint8_t bsec_config[] = {
#include "config/generic_33v_3s_28d/bsec_iaq.txt" #include "config/generic_33v_3s_28d/bsec_iaq.txt"
}; };
this->set_config_(bsec_config); this->set_config_(bsec_config);
this->update_subscription_(BSEC_SAMPLE_RATE_LP);
} }
this->update_subscription_();
if (this->bsec_status_ != BSEC_OK) { if (this->bsec_status_ != BSEC_OK) {
this->mark_failed(); this->mark_failed();
return; return;
@ -64,50 +60,57 @@ void BME680BSECComponent::set_config_(const uint8_t *config) {
this->bsec_status_ = bsec_set_configuration(config, BSEC_MAX_PROPERTY_BLOB_SIZE, work_buffer, sizeof(work_buffer)); this->bsec_status_ = bsec_set_configuration(config, BSEC_MAX_PROPERTY_BLOB_SIZE, work_buffer, sizeof(work_buffer));
} }
void BME680BSECComponent::update_subscription_(float sample_rate) { float BME680BSECComponent::calc_sensor_sample_rate_(SampleRate sample_rate) {
if (sample_rate == SAMPLE_RATE_DEFAULT) {
sample_rate = this->sample_rate_;
}
return sample_rate == SAMPLE_RATE_ULP ? BSEC_SAMPLE_RATE_ULP : BSEC_SAMPLE_RATE_LP;
}
void BME680BSECComponent::update_subscription_() {
bsec_sensor_configuration_t virtual_sensors[BSEC_NUMBER_OUTPUTS]; bsec_sensor_configuration_t virtual_sensors[BSEC_NUMBER_OUTPUTS];
int num_virtual_sensors = 0; int num_virtual_sensors = 0;
if (this->iaq_sensor_) { if (this->iaq_sensor_) {
virtual_sensors[num_virtual_sensors].sensor_id = virtual_sensors[num_virtual_sensors].sensor_id =
this->iaq_mode_ == IAQ_MODE_STATIC ? BSEC_OUTPUT_STATIC_IAQ : BSEC_OUTPUT_IAQ; this->iaq_mode_ == IAQ_MODE_STATIC ? BSEC_OUTPUT_STATIC_IAQ : BSEC_OUTPUT_IAQ;
virtual_sensors[num_virtual_sensors].sample_rate = sample_rate; virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT);
num_virtual_sensors++; num_virtual_sensors++;
} }
if (this->co2_equivalent_sensor_) { if (this->co2_equivalent_sensor_) {
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_CO2_EQUIVALENT; virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_CO2_EQUIVALENT;
virtual_sensors[num_virtual_sensors].sample_rate = sample_rate; virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT);
num_virtual_sensors++; num_virtual_sensors++;
} }
if (this->breath_voc_equivalent_sensor_) { if (this->breath_voc_equivalent_sensor_) {
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_BREATH_VOC_EQUIVALENT; virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_BREATH_VOC_EQUIVALENT;
virtual_sensors[num_virtual_sensors].sample_rate = sample_rate; virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT);
num_virtual_sensors++; num_virtual_sensors++;
} }
if (this->pressure_sensor_) { if (this->pressure_sensor_) {
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_PRESSURE; virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_PRESSURE;
virtual_sensors[num_virtual_sensors].sample_rate = sample_rate; virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(this->pressure_sample_rate_);
num_virtual_sensors++; num_virtual_sensors++;
} }
if (this->gas_resistance_sensor_) { if (this->gas_resistance_sensor_) {
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_GAS; virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_RAW_GAS;
virtual_sensors[num_virtual_sensors].sample_rate = sample_rate; virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(SAMPLE_RATE_DEFAULT);
num_virtual_sensors++; num_virtual_sensors++;
} }
if (this->temperature_sensor_) { if (this->temperature_sensor_) {
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE; virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE;
virtual_sensors[num_virtual_sensors].sample_rate = sample_rate; virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(this->temperature_sample_rate_);
num_virtual_sensors++; num_virtual_sensors++;
} }
if (this->humidity_sensor_) { if (this->humidity_sensor_) {
virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY; virtual_sensors[num_virtual_sensors].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY;
virtual_sensors[num_virtual_sensors].sample_rate = sample_rate; virtual_sensors[num_virtual_sensors].sample_rate = this->calc_sensor_sample_rate_(this->humidity_sample_rate_);
num_virtual_sensors++; num_virtual_sensors++;
} }
@ -134,12 +137,15 @@ void BME680BSECComponent::dump_config() {
ESP_LOGCONFIG(TAG, " Temperature Offset: %.2f", this->temperature_offset_); ESP_LOGCONFIG(TAG, " Temperature Offset: %.2f", this->temperature_offset_);
ESP_LOGCONFIG(TAG, " IAQ Mode: %s", this->iaq_mode_ == IAQ_MODE_STATIC ? "Static" : "Mobile"); ESP_LOGCONFIG(TAG, " IAQ Mode: %s", this->iaq_mode_ == IAQ_MODE_STATIC ? "Static" : "Mobile");
ESP_LOGCONFIG(TAG, " Sample Rate: %s", this->sample_rate_ == SAMPLE_RATE_ULP ? "ULP" : "LP"); ESP_LOGCONFIG(TAG, " Sample Rate: %s", BME680_BSEC_SAMPLE_RATE_LOG(this->sample_rate_));
ESP_LOGCONFIG(TAG, " State Save Interval: %ims", this->state_save_interval_ms_); ESP_LOGCONFIG(TAG, " State Save Interval: %ims", this->state_save_interval_ms_);
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
ESP_LOGCONFIG(TAG, " Sample Rate: %s", BME680_BSEC_SAMPLE_RATE_LOG(this->temperature_sample_rate_));
LOG_SENSOR(" ", "Pressure", this->pressure_sensor_); LOG_SENSOR(" ", "Pressure", this->pressure_sensor_);
ESP_LOGCONFIG(TAG, " Sample Rate: %s", BME680_BSEC_SAMPLE_RATE_LOG(this->pressure_sample_rate_));
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
ESP_LOGCONFIG(TAG, " Sample Rate: %s", BME680_BSEC_SAMPLE_RATE_LOG(this->humidity_sample_rate_));
LOG_SENSOR(" ", "Gas Resistance", this->gas_resistance_sensor_); LOG_SENSOR(" ", "Gas Resistance", this->gas_resistance_sensor_);
LOG_SENSOR(" ", "IAQ", this->iaq_sensor_); LOG_SENSOR(" ", "IAQ", this->iaq_sensor_);
LOG_SENSOR(" ", "Numeric IAQ Accuracy", this->iaq_accuracy_sensor_); LOG_SENSOR(" ", "Numeric IAQ Accuracy", this->iaq_accuracy_sensor_);
@ -181,34 +187,55 @@ void BME680BSECComponent::run_() {
} }
this->next_call_ns_ = bme680_settings.next_call; this->next_call_ns_ = bme680_settings.next_call;
this->bme680_.gas_sett.run_gas = bme680_settings.run_gas; if (bme680_settings.trigger_measurement) {
this->bme680_.tph_sett.os_hum = bme680_settings.humidity_oversampling; this->bme680_.tph_sett.os_temp = bme680_settings.temperature_oversampling;
this->bme680_.tph_sett.os_temp = bme680_settings.temperature_oversampling; this->bme680_.tph_sett.os_pres = bme680_settings.pressure_oversampling;
this->bme680_.tph_sett.os_pres = bme680_settings.pressure_oversampling; this->bme680_.tph_sett.os_hum = bme680_settings.humidity_oversampling;
this->bme680_.gas_sett.heatr_temp = bme680_settings.heater_temperature; this->bme680_.gas_sett.run_gas = bme680_settings.run_gas;
this->bme680_.gas_sett.heatr_dur = bme680_settings.heating_duration; this->bme680_.gas_sett.heatr_temp = bme680_settings.heater_temperature;
uint16_t desired_settings = this->bme680_.gas_sett.heatr_dur = bme680_settings.heating_duration;
BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; this->bme680_.power_mode = BME680_FORCED_MODE;
this->bme680_status_ = bme680_set_sensor_settings(desired_settings, &this->bme680_); uint16_t desired_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_GAS_SENSOR_SEL;
if (this->bme680_status_ != BME680_OK) { this->bme680_status_ = bme680_set_sensor_settings(desired_settings, &this->bme680_);
ESP_LOGW(TAG, "Failed to set sensor settings (BME680 Error Code %d)", this->bme680_status_); if (this->bme680_status_ != BME680_OK) {
return; ESP_LOGW(TAG, "Failed to set sensor settings (BME680 Error Code %d)", this->bme680_status_);
} return;
}
this->bme680_status_ = bme680_set_sensor_mode(&this->bme680_); this->bme680_status_ = bme680_set_sensor_mode(&this->bme680_);
if (this->bme680_status_ != BME680_OK) { if (this->bme680_status_ != BME680_OK) {
ESP_LOGW(TAG, "Failed to set sensor mode (BME680 Error Code %d)", this->bme680_status_); ESP_LOGW(TAG, "Failed to set sensor mode (BME680 Error Code %d)", this->bme680_status_);
return; return;
} }
uint16_t meas_dur = 0; uint16_t meas_dur = 0;
bme680_get_profile_dur(&meas_dur, &this->bme680_); bme680_get_profile_dur(&meas_dur, &this->bme680_);
ESP_LOGV(TAG, "Queueing read in %ums", meas_dur); ESP_LOGV(TAG, "Queueing read in %ums", meas_dur);
this->set_timeout("read", meas_dur, [this, bme680_settings]() { this->read_(bme680_settings); }); this->set_timeout("read", meas_dur,
[this, curr_time_ns, bme680_settings]() { this->read_(curr_time_ns, bme680_settings); });
} else {
ESP_LOGV(TAG, "Measurement not required");
this->read_(curr_time_ns, bme680_settings);
}
} }
void BME680BSECComponent::read_(bsec_bme_settings_t bme680_settings) { void BME680BSECComponent::read_(int64_t trigger_time_ns, bsec_bme_settings_t bme680_settings) {
ESP_LOGV(TAG, "Reading data"); ESP_LOGV(TAG, "Reading data");
if (bme680_settings.trigger_measurement) {
while (this->bme680_.power_mode != BME680_SLEEP_MODE) {
this->bme680_status_ = bme680_get_sensor_mode(&this->bme680_);
if (this->bme680_status_ != BME680_OK) {
ESP_LOGW(TAG, "Failed to get sensor mode (BME680 Error Code %d)", this->bme680_status_);
}
}
}
if (!bme680_settings.process_data) {
ESP_LOGV(TAG, "Data processing not required");
return;
}
struct bme680_field_data data; struct bme680_field_data data;
this->bme680_status_ = bme680_get_sensor_data(&data, &this->bme680_); this->bme680_status_ = bme680_get_sensor_data(&data, &this->bme680_);
@ -223,37 +250,40 @@ void BME680BSECComponent::read_(bsec_bme_settings_t bme680_settings) {
bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temperature, Pressure, Humidity & Gas Resistance bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temperature, Pressure, Humidity & Gas Resistance
uint8_t num_inputs = 0; uint8_t num_inputs = 0;
int64_t curr_time_ns = this->get_time_ns_();
if (bme680_settings.process_data & BSEC_PROCESS_TEMPERATURE) { if (bme680_settings.process_data & BSEC_PROCESS_TEMPERATURE) {
inputs[num_inputs].sensor_id = BSEC_INPUT_TEMPERATURE; inputs[num_inputs].sensor_id = BSEC_INPUT_TEMPERATURE;
inputs[num_inputs].signal = data.temperature / 100.0f; inputs[num_inputs].signal = data.temperature / 100.0f;
inputs[num_inputs].time_stamp = curr_time_ns; inputs[num_inputs].time_stamp = trigger_time_ns;
num_inputs++; num_inputs++;
// Temperature offset from the real temperature due to external heat sources // Temperature offset from the real temperature due to external heat sources
inputs[num_inputs].sensor_id = BSEC_INPUT_HEATSOURCE; inputs[num_inputs].sensor_id = BSEC_INPUT_HEATSOURCE;
inputs[num_inputs].signal = this->temperature_offset_; inputs[num_inputs].signal = this->temperature_offset_;
inputs[num_inputs].time_stamp = curr_time_ns; inputs[num_inputs].time_stamp = trigger_time_ns;
num_inputs++; num_inputs++;
} }
if (bme680_settings.process_data & BSEC_PROCESS_HUMIDITY) { if (bme680_settings.process_data & BSEC_PROCESS_HUMIDITY) {
inputs[num_inputs].sensor_id = BSEC_INPUT_HUMIDITY; inputs[num_inputs].sensor_id = BSEC_INPUT_HUMIDITY;
inputs[num_inputs].signal = data.humidity / 1000.0f; inputs[num_inputs].signal = data.humidity / 1000.0f;
inputs[num_inputs].time_stamp = curr_time_ns; inputs[num_inputs].time_stamp = trigger_time_ns;
num_inputs++; num_inputs++;
} }
if (bme680_settings.process_data & BSEC_PROCESS_PRESSURE) { if (bme680_settings.process_data & BSEC_PROCESS_PRESSURE) {
inputs[num_inputs].sensor_id = BSEC_INPUT_PRESSURE; inputs[num_inputs].sensor_id = BSEC_INPUT_PRESSURE;
inputs[num_inputs].signal = data.pressure; inputs[num_inputs].signal = data.pressure;
inputs[num_inputs].time_stamp = curr_time_ns; inputs[num_inputs].time_stamp = trigger_time_ns;
num_inputs++; num_inputs++;
} }
if (bme680_settings.process_data & BSEC_PROCESS_GAS) { if (bme680_settings.process_data & BSEC_PROCESS_GAS) {
inputs[num_inputs].sensor_id = BSEC_INPUT_GASRESISTOR; if (data.status & BME680_GASM_VALID_MSK) {
inputs[num_inputs].signal = data.gas_resistance; inputs[num_inputs].sensor_id = BSEC_INPUT_GASRESISTOR;
inputs[num_inputs].time_stamp = curr_time_ns; inputs[num_inputs].signal = data.gas_resistance;
num_inputs++; inputs[num_inputs].time_stamp = trigger_time_ns;
num_inputs++;
} else {
ESP_LOGD(TAG, "BME680 did not report gas data");
}
} }
if (num_inputs < 1) { if (num_inputs < 1) {
ESP_LOGD(TAG, "No signal inputs available for BSEC"); ESP_LOGD(TAG, "No signal inputs available for BSEC");

View file

@ -1,5 +1,3 @@
#pragma once #pragma once
#include "esphome/core/component.h" #include "esphome/core/component.h"
@ -9,13 +7,13 @@
#include "esphome/core/preferences.h" #include "esphome/core/preferences.h"
#include <map> #include <map>
#ifdef USING_BSEC #ifdef USE_BSEC
#include <bsec.h> #include <bsec.h>
#endif #endif
namespace esphome { namespace esphome {
namespace bme680_bsec { namespace bme680_bsec {
#ifdef USING_BSEC #ifdef USE_BSEC
enum IAQMode { enum IAQMode {
IAQ_MODE_STATIC = 0, IAQ_MODE_STATIC = 0,
@ -25,32 +23,31 @@ enum IAQMode {
enum SampleRate { enum SampleRate {
SAMPLE_RATE_LP = 0, SAMPLE_RATE_LP = 0,
SAMPLE_RATE_ULP = 1, SAMPLE_RATE_ULP = 1,
SAMPLE_RATE_DEFAULT = 2,
}; };
#define BME680_BSEC_SAMPLE_RATE_LOG(r) (r == SAMPLE_RATE_DEFAULT ? "Default" : (r == SAMPLE_RATE_ULP ? "ULP" : "LP"))
class BME680BSECComponent : public Component, public i2c::I2CDevice { class BME680BSECComponent : public Component, public i2c::I2CDevice {
public: public:
void set_temperature_offset(float offset) { this->temperature_offset_ = offset; } void set_temperature_offset(float offset) { this->temperature_offset_ = offset; }
void set_iaq_mode(IAQMode iaq_mode) { this->iaq_mode_ = iaq_mode; } void set_iaq_mode(IAQMode iaq_mode) { this->iaq_mode_ = iaq_mode; }
void set_sample_rate(SampleRate sample_rate) { this->sample_rate_ = sample_rate; }
void set_state_save_interval(uint32_t interval) { this->state_save_interval_ms_ = interval; } void set_state_save_interval(uint32_t interval) { this->state_save_interval_ms_ = interval; }
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } void set_sample_rate(SampleRate sample_rate) { this->sample_rate_ = sample_rate; }
void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; } void set_temperature_sample_rate(SampleRate sample_rate) { this->temperature_sample_rate_ = sample_rate; }
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; } void set_pressure_sample_rate(SampleRate sample_rate) { this->pressure_sample_rate_ = sample_rate; }
void set_gas_resistance_sensor(sensor::Sensor *gas_resistance_sensor) { void set_humidity_sample_rate(SampleRate sample_rate) { this->humidity_sample_rate_ = sample_rate; }
gas_resistance_sensor_ = gas_resistance_sensor;
} void set_temperature_sensor(sensor::Sensor *sensor) { this->temperature_sensor_ = sensor; }
void set_iaq_sensor(sensor::Sensor *iaq_sensor) { iaq_sensor_ = iaq_sensor; } void set_pressure_sensor(sensor::Sensor *sensor) { this->pressure_sensor_ = sensor; }
void set_iaq_accuracy_text_sensor(text_sensor::TextSensor *iaq_accuracy_text_sensor) { void set_humidity_sensor(sensor::Sensor *sensor) { this->humidity_sensor_ = sensor; }
iaq_accuracy_text_sensor_ = iaq_accuracy_text_sensor; void set_gas_resistance_sensor(sensor::Sensor *sensor) { this->gas_resistance_sensor_ = sensor; }
} void set_iaq_sensor(sensor::Sensor *sensor) { this->iaq_sensor_ = sensor; }
void set_iaq_accuracy_sensor(sensor::Sensor *iaq_accuracy_sensor) { iaq_accuracy_sensor_ = iaq_accuracy_sensor; } void set_iaq_accuracy_text_sensor(text_sensor::TextSensor *sensor) { this->iaq_accuracy_text_sensor_ = sensor; }
void set_co2_equivalent_sensor(sensor::Sensor *co2_equivalent_sensor) { void set_iaq_accuracy_sensor(sensor::Sensor *sensor) { this->iaq_accuracy_sensor_ = sensor; }
co2_equivalent_sensor_ = co2_equivalent_sensor; void set_co2_equivalent_sensor(sensor::Sensor *sensor) { this->co2_equivalent_sensor_ = sensor; }
} void set_breath_voc_equivalent_sensor(sensor::Sensor *sensor) { this->breath_voc_equivalent_sensor_ = sensor; }
void set_breath_voc_equivalent_sensor(sensor::Sensor *breath_voc_equivalent_sensor) {
breath_voc_equivalent_sensor_ = breath_voc_equivalent_sensor;
}
static BME680BSECComponent *instance; static BME680BSECComponent *instance;
static int8_t read_bytes_wrapper(uint8_t address, uint8_t a_register, uint8_t *data, uint16_t len); static int8_t read_bytes_wrapper(uint8_t address, uint8_t a_register, uint8_t *data, uint16_t len);
@ -64,10 +61,11 @@ class BME680BSECComponent : public Component, public i2c::I2CDevice {
protected: protected:
void set_config_(const uint8_t *config); void set_config_(const uint8_t *config);
void update_subscription_(float sample_rate); float calc_sensor_sample_rate_(SampleRate sample_rate);
void update_subscription_();
void run_(); void run_();
void read_(bsec_bme_settings_t bme680_settings); void read_(int64_t trigger_time_ns, bsec_bme_settings_t bme680_settings);
void publish_(const bsec_output_t *outputs, uint8_t num_outputs); void publish_(const bsec_output_t *outputs, uint8_t num_outputs);
int64_t get_time_ns_(); int64_t get_time_ns_();
@ -91,7 +89,11 @@ class BME680BSECComponent : public Component, public i2c::I2CDevice {
float temperature_offset_{0}; float temperature_offset_{0};
IAQMode iaq_mode_{IAQ_MODE_STATIC}; IAQMode iaq_mode_{IAQ_MODE_STATIC};
SampleRate sample_rate_{SAMPLE_RATE_LP};
SampleRate sample_rate_{SAMPLE_RATE_LP}; // Core/gas sample rate
SampleRate temperature_sample_rate_{SAMPLE_RATE_DEFAULT};
SampleRate pressure_sample_rate_{SAMPLE_RATE_DEFAULT};
SampleRate humidity_sample_rate_{SAMPLE_RATE_DEFAULT};
sensor::Sensor *temperature_sensor_; sensor::Sensor *temperature_sensor_;
sensor::Sensor *pressure_sensor_; sensor::Sensor *pressure_sensor_;

View file

@ -22,7 +22,12 @@ from esphome.const import (
ICON_WATER_PERCENT, ICON_WATER_PERCENT,
) )
from esphome.core import coroutine from esphome.core import coroutine
from . import BME680BSECComponent, CONF_BME680_BSEC_ID from . import (
BME680BSECComponent,
CONF_BME680_BSEC_ID,
CONF_SAMPLE_RATE,
SAMPLE_RATE_OPTIONS,
)
DEPENDENCIES = ["bme680_bsec"] DEPENDENCIES = ["bme680_bsec"]
@ -34,28 +39,34 @@ UNIT_IAQ = "IAQ"
ICON_ACCURACY = "mdi:checkbox-marked-circle-outline" ICON_ACCURACY = "mdi:checkbox-marked-circle-outline"
ICON_TEST_TUBE = "mdi:test-tube" ICON_TEST_TUBE = "mdi:test-tube"
TYPES = { TYPES = [
CONF_TEMPERATURE: "set_temperature_sensor", CONF_TEMPERATURE,
CONF_PRESSURE: "set_pressure_sensor", CONF_PRESSURE,
CONF_HUMIDITY: "set_humidity_sensor", CONF_HUMIDITY,
CONF_GAS_RESISTANCE: "set_gas_resistance_sensor", CONF_GAS_RESISTANCE,
CONF_IAQ: "set_iaq_sensor", CONF_IAQ,
CONF_IAQ_ACCURACY: "set_iaq_accuracy_sensor", CONF_IAQ_ACCURACY,
CONF_CO2_EQUIVALENT: "set_co2_equivalent_sensor", CONF_CO2_EQUIVALENT,
CONF_BREATH_VOC_EQUIVALENT: "set_breath_voc_equivalent_sensor", CONF_BREATH_VOC_EQUIVALENT,
} ]
CONFIG_SCHEMA = cv.Schema( CONFIG_SCHEMA = cv.Schema(
{ {
cv.GenerateID(CONF_BME680_BSEC_ID): cv.use_id(BME680BSECComponent), cv.GenerateID(CONF_BME680_BSEC_ID): cv.use_id(BME680BSECComponent),
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
UNIT_CELSIUS, ICON_THERMOMETER, 1, DEVICE_CLASS_TEMPERATURE UNIT_CELSIUS, ICON_THERMOMETER, 1, DEVICE_CLASS_TEMPERATURE
).extend(
{cv.Optional(CONF_SAMPLE_RATE): cv.enum(SAMPLE_RATE_OPTIONS, upper=True)}
), ),
cv.Optional(CONF_PRESSURE): sensor.sensor_schema( cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
UNIT_HECTOPASCAL, ICON_GAUGE, 1, DEVICE_CLASS_PRESSURE UNIT_HECTOPASCAL, ICON_GAUGE, 1, DEVICE_CLASS_PRESSURE
).extend(
{cv.Optional(CONF_SAMPLE_RATE): cv.enum(SAMPLE_RATE_OPTIONS, upper=True)}
), ),
cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
UNIT_PERCENT, ICON_WATER_PERCENT, 1, DEVICE_CLASS_HUMIDITY UNIT_PERCENT, ICON_WATER_PERCENT, 1, DEVICE_CLASS_HUMIDITY
).extend(
{cv.Optional(CONF_SAMPLE_RATE): cv.enum(SAMPLE_RATE_OPTIONS, upper=True)}
), ),
cv.Optional(CONF_GAS_RESISTANCE): sensor.sensor_schema( cv.Optional(CONF_GAS_RESISTANCE): sensor.sensor_schema(
UNIT_OHM, ICON_GAS_CYLINDER, 0, DEVICE_CLASS_EMPTY UNIT_OHM, ICON_GAS_CYLINDER, 0, DEVICE_CLASS_EMPTY
@ -77,15 +88,16 @@ CONFIG_SCHEMA = cv.Schema(
@coroutine @coroutine
def setup_conf(config, key, hub, funcName): def setup_conf(config, key, hub):
if key in config: if key in config:
conf = config[key] conf = config[key]
var = yield sensor.new_sensor(conf) sens = yield sensor.new_sensor(conf)
func = getattr(hub, funcName) cg.add(getattr(hub, f"set_{key}_sensor")(sens))
cg.add(func(var)) if CONF_SAMPLE_RATE in conf:
cg.add(getattr(hub, f"set_{key}_sample_rate")(conf[CONF_SAMPLE_RATE]))
def to_code(config): def to_code(config):
hub = yield cg.get_variable(config[CONF_BME680_BSEC_ID]) hub = yield cg.get_variable(config[CONF_BME680_BSEC_ID])
for key, funcName in TYPES.items(): for key in TYPES:
yield setup_conf(config, key, hub, funcName) yield setup_conf(config, key, hub)

View file

@ -10,7 +10,7 @@ DEPENDENCIES = ["bme680_bsec"]
CONF_IAQ_ACCURACY = "iaq_accuracy" CONF_IAQ_ACCURACY = "iaq_accuracy"
ICON_ACCURACY = "mdi:checkbox-marked-circle-outline" ICON_ACCURACY = "mdi:checkbox-marked-circle-outline"
TYPES = {CONF_IAQ_ACCURACY: "set_iaq_accuracy_text_sensor"} TYPES = [CONF_IAQ_ACCURACY]
CONFIG_SCHEMA = cv.Schema( CONFIG_SCHEMA = cv.Schema(
{ {
@ -26,16 +26,15 @@ CONFIG_SCHEMA = cv.Schema(
@coroutine @coroutine
def setup_conf(config, key, hub, funcName): def setup_conf(config, key, hub):
if key in config: if key in config:
conf = config[key] conf = config[key]
var = cg.new_Pvariable(conf[CONF_ID]) sens = cg.new_Pvariable(conf[CONF_ID])
yield text_sensor.register_text_sensor(var, conf) yield text_sensor.register_text_sensor(sens, conf)
func = getattr(hub, funcName) cg.add(getattr(hub, f"set_{key}_text_sensor")(sens))
cg.add(func(var))
def to_code(config): def to_code(config):
hub = yield cg.get_variable(config[CONF_BME680_BSEC_ID]) hub = yield cg.get_variable(config[CONF_BME680_BSEC_ID])
for key, funcName in TYPES.items(): for key in TYPES:
yield setup_conf(config, key, hub, funcName) yield setup_conf(config, key, hub)