Queue sensor publishes so we don't block for too long (#3422)

This commit is contained in:
Trevor North 2022-04-26 20:51:22 +01:00 committed by GitHub
parent 2bff9937b7
commit ebf13a0ba0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 19 deletions

View file

@ -169,6 +169,14 @@ void BME680BSECComponent::loop() {
} else { } else {
this->status_clear_warning(); this->status_clear_warning();
} }
// Process a single action from the queue. These are primarily sensor state publishes
// that in totality take too long to send in a single call.
if (this->queue_.size()) {
auto action = std::move(this->queue_.front());
this->queue_.pop();
action();
}
} }
void BME680BSECComponent::run_() { void BME680BSECComponent::run_() {
@ -306,37 +314,39 @@ void BME680BSECComponent::read_(int64_t trigger_time_ns, bsec_bme_settings_t bme
} }
void BME680BSECComponent::publish_(const bsec_output_t *outputs, uint8_t num_outputs) { void BME680BSECComponent::publish_(const bsec_output_t *outputs, uint8_t num_outputs) {
ESP_LOGV(TAG, "Publishing sensor states"); ESP_LOGV(TAG, "Queuing sensor state publish actions");
for (uint8_t i = 0; i < num_outputs; i++) { for (uint8_t i = 0; i < num_outputs; i++) {
float signal = outputs[i].signal;
switch (outputs[i].sensor_id) { switch (outputs[i].sensor_id) {
case BSEC_OUTPUT_IAQ: case BSEC_OUTPUT_IAQ:
case BSEC_OUTPUT_STATIC_IAQ: case BSEC_OUTPUT_STATIC_IAQ: {
uint8_t accuracy; uint8_t accuracy = outputs[i].accuracy;
accuracy = outputs[i].accuracy; this->queue_push_([this, signal]() { this->publish_sensor_(this->iaq_sensor_, signal); });
this->publish_sensor_state_(this->iaq_sensor_, outputs[i].signal); this->queue_push_([this, accuracy]() {
this->publish_sensor_state_(this->iaq_accuracy_text_sensor_, IAQ_ACCURACY_STATES[accuracy]); this->publish_sensor_(this->iaq_accuracy_text_sensor_, IAQ_ACCURACY_STATES[accuracy]);
this->publish_sensor_state_(this->iaq_accuracy_sensor_, accuracy, true); });
this->queue_push_([this, accuracy]() { this->publish_sensor_(this->iaq_accuracy_sensor_, accuracy, true); });
// Queue up an opportunity to save state // Queue up an opportunity to save state
this->defer("save_state", [this, accuracy]() { this->save_state_(accuracy); }); this->queue_push_([this, accuracy]() { this->save_state_(accuracy); });
break; } break;
case BSEC_OUTPUT_CO2_EQUIVALENT: case BSEC_OUTPUT_CO2_EQUIVALENT:
this->publish_sensor_state_(this->co2_equivalent_sensor_, outputs[i].signal); this->queue_push_([this, signal]() { this->publish_sensor_(this->co2_equivalent_sensor_, signal); });
break; break;
case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT: case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
this->publish_sensor_state_(this->breath_voc_equivalent_sensor_, outputs[i].signal); this->queue_push_([this, signal]() { this->publish_sensor_(this->breath_voc_equivalent_sensor_, signal); });
break; break;
case BSEC_OUTPUT_RAW_PRESSURE: case BSEC_OUTPUT_RAW_PRESSURE:
this->publish_sensor_state_(this->pressure_sensor_, outputs[i].signal / 100.0f); this->queue_push_([this, signal]() { this->publish_sensor_(this->pressure_sensor_, signal / 100.0f); });
break; break;
case BSEC_OUTPUT_RAW_GAS: case BSEC_OUTPUT_RAW_GAS:
this->publish_sensor_state_(this->gas_resistance_sensor_, outputs[i].signal); this->queue_push_([this, signal]() { this->publish_sensor_(this->gas_resistance_sensor_, signal); });
break; break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE: case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
this->publish_sensor_state_(this->temperature_sensor_, outputs[i].signal); this->queue_push_([this, signal]() { this->publish_sensor_(this->temperature_sensor_, signal); });
break; break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY: case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
this->publish_sensor_state_(this->humidity_sensor_, outputs[i].signal); this->queue_push_([this, signal]() { this->publish_sensor_(this->humidity_sensor_, signal); });
break; break;
} }
} }
@ -352,14 +362,14 @@ int64_t BME680BSECComponent::get_time_ns_() {
return (time_ms + ((int64_t) this->millis_overflow_counter_ << 32)) * INT64_C(1000000); return (time_ms + ((int64_t) this->millis_overflow_counter_ << 32)) * INT64_C(1000000);
} }
void BME680BSECComponent::publish_sensor_state_(sensor::Sensor *sensor, float value, bool change_only) { void BME680BSECComponent::publish_sensor_(sensor::Sensor *sensor, float value, bool change_only) {
if (!sensor || (change_only && sensor->has_state() && sensor->state == value)) { if (!sensor || (change_only && sensor->has_state() && sensor->state == value)) {
return; return;
} }
sensor->publish_state(value); sensor->publish_state(value);
} }
void BME680BSECComponent::publish_sensor_state_(text_sensor::TextSensor *sensor, const std::string &value) { void BME680BSECComponent::publish_sensor_(text_sensor::TextSensor *sensor, const std::string &value) {
if (!sensor || (sensor->has_state() && sensor->state == value)) { if (!sensor || (sensor->has_state() && sensor->state == value)) {
return; return;
} }

View file

@ -70,12 +70,14 @@ class BME680BSECComponent : public Component, public i2c::I2CDevice {
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_();
void publish_sensor_state_(sensor::Sensor *sensor, float value, bool change_only = false); void publish_sensor_(sensor::Sensor *sensor, float value, bool change_only = false);
void publish_sensor_state_(text_sensor::TextSensor *sensor, const std::string &value); void publish_sensor_(text_sensor::TextSensor *sensor, const std::string &value);
void load_state_(); void load_state_();
void save_state_(uint8_t accuracy); void save_state_(uint8_t accuracy);
void queue_push_(std::function<void()> &&f) { this->queue_.push(std::move(f)); }
struct bme680_dev bme680_; struct bme680_dev bme680_;
bsec_library_return_t bsec_status_{BSEC_OK}; bsec_library_return_t bsec_status_{BSEC_OK};
int8_t bme680_status_{BME680_OK}; int8_t bme680_status_{BME680_OK};
@ -84,6 +86,8 @@ class BME680BSECComponent : public Component, public i2c::I2CDevice {
uint32_t millis_overflow_counter_{0}; uint32_t millis_overflow_counter_{0};
int64_t next_call_ns_{0}; int64_t next_call_ns_{0};
std::queue<std::function<void()>> queue_;
ESPPreferenceObject bsec_state_; ESPPreferenceObject bsec_state_;
uint32_t state_save_interval_ms_{21600000}; // 6 hours - 4 times a day uint32_t state_save_interval_ms_{21600000}; // 6 hours - 4 times a day
uint32_t last_state_save_ms_ = 0; uint32_t last_state_save_ms_ = 0;