mirror of
https://github.com/esphome/esphome.git
synced 2024-11-22 06:58:11 +01:00
BME680 BSEC: Allow sample rate overrides for T/P/H sensors (#1710)
This commit is contained in:
parent
063d9c47a4
commit
cccb1a2c9e
5 changed files with 141 additions and 98 deletions
|
@ -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")
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue