#include "bme280_sensor.h"
Bme280Sensor::Bme280Sensor() {
}
Bme280Sensor::~Bme280Sensor() {
if (_bme280 != nullptr) {
delete _bme280;
_bme280 = nullptr;
}
if (_bmp280 != nullptr) {
delete _bmp280;
_bmp280 = nullptr;
}
}
bool Bme280Sensor::begin(TwoWire &wire, const Bme280Config &config) {
_config = config;
_wire = &wire;
_wire -> begin(_config.sda_pin, _config.scl_pin, 400000);
/*
На случай повторной инициализации.
*/
if (_bme280 != nullptr) {
delete _bme280;
_bme280 = nullptr;
}
if (_bmp280 != nullptr) {
delete _bmp280;
_bmp280 = nullptr;
}
_sensor_type = BME_SENSOR_TYPE_UNKNOWN;
_initialized = false;
_online = false;
_has_valid_data = false;
_last_read_attempt_ms = 0;
_last_success_read_ms = 0;
_temperature_c = 0.0f;
_pressure_hpa = 0.0f;
_humidity_percent = 0.0f;
_filtered_temperature_c = 0.0f;
_filtered_pressure_hpa = 0.0f;
_filtered_humidity_percent = 0.0f;
/*
Сначала пробуем BME280.
*/
if (init_bme280()) {
_sensor_type = BME_SENSOR_TYPE_BME280;
_initialized = true;
_online = true;
return true;
}
/*
Если не вышло, пробуем BMP280.
*/
if (init_bmp280()) {
_sensor_type = BME_SENSOR_TYPE_BMP280;
_initialized = true;
_online = true;
return true;
}
_sensor_type = BME_SENSOR_TYPE_UNKNOWN;
_initialized = false;
_online = false;
return false;
}
void Bme280Sensor::update() {
if (!_initialized) {
return;
}
uint32_t now_ms = millis();
if (now_ms - _last_read_attempt_ms < _config.read_interval_ms) {
return;
}
_last_read_attempt_ms = now_ms;
float temperature = 0.0f;
float pressure = 0.0f;
float humidity = 0.0f;
if (_sensor_type == BME_SENSOR_TYPE_BME280) {
if (_bme280 == nullptr) {
_online = false;
return;
}
temperature = _bme280 -> readTemperature();
pressure = _bme280 -> readPressure() / 100.0f;
humidity = _bme280 -> readHumidity();
if (isnan(temperature) || isnan(pressure) || isnan(humidity)) {
_online = false;
return;
}
_temperature_c = temperature;
_pressure_hpa = pressure;
_humidity_percent = humidity;
update_filtered_temperature(temperature);
update_filtered_pressure(pressure);
update_filtered_humidity(humidity);
} else if (_sensor_type == BME_SENSOR_TYPE_BMP280) {
if (_bmp280 == nullptr) {
_online = false;
return;
}
temperature = _bmp280 -> readTemperature();
pressure = _bmp280 -> readPressure() / 100.0f;
if (isnan(temperature) || isnan(pressure)) {
_online = false;
return;
}
_temperature_c = temperature;
_pressure_hpa = pressure;
_humidity_percent = 0.0f;
update_filtered_temperature(temperature);
update_filtered_pressure(pressure);
}
_online = true;
_has_valid_data = true;
_last_success_read_ms = now_ms;
}
bool Bme280Sensor::is_online() const {
return _online;
}
bool Bme280Sensor::has_valid_data() const {
return _has_valid_data;
}
bool Bme280Sensor::is_stale() const {
if (!_has_valid_data) {
return true;
}
uint32_t now_ms = millis();
return (now_ms - _last_success_read_ms) > _config.stale_after_ms;
}
BmeSensorType Bme280Sensor::get_sensor_type() const {
return _sensor_type;
}
String Bme280Sensor::get_sensor_type_string() const {
if (_sensor_type == BME_SENSOR_TYPE_BME280) {
return "bme280";
}
if (_sensor_type == BME_SENSOR_TYPE_BMP280) {
return "bmp280";
}
return "unknown";
}
float Bme280Sensor::get_temperature_c() const {
return _filtered_temperature_c;
}
float Bme280Sensor::get_pressure_hpa() const {
return _filtered_pressure_hpa;
}
float Bme280Sensor::get_humidity_percent() const {
return _filtered_humidity_percent;
}
bool Bme280Sensor::has_humidity() const {
return _sensor_type == BME_SENSOR_TYPE_BME280;
}
String Bme280Sensor::get_state_json() const {
String json = "{";
json += "\"sensor\":\"" + get_sensor_type_string() + "\",";
json += "\"online\":" + String(_online ? "true" : "false") + ",";
json += "\"has_valid_data\":" + String(_has_valid_data ? "true" : "false") + ",";
json += "\"stale\":" + String(is_stale() ? "true" : "false") + ",";
json += "\"i2c_address\":\"0x" + String(_config.i2c_address, HEX) + "\",";
json += "\"data\":{";
json += "\"temperature_c\":" + String(_filtered_temperature_c, 2) + ",";
json += "\"pressure_hpa\":" + String(_filtered_pressure_hpa, 2);
if (has_humidity()) {
json += ",";
json += "\"humidity_percent\":" + String(_filtered_humidity_percent, 2);
}
json += "}";
json += "}";
return json;
}
bool Bme280Sensor::init_bme280() {
if (_wire == nullptr) {
return false;
}
_bme280 = new Adafruit_BME280();
if (_bme280 == nullptr) {
return false;
}
bool ok = _bme280 -> begin(_config.i2c_address, _wire);
if (!ok) {
delete _bme280;
_bme280 = nullptr;
return false;
}
_bme280 -> setSampling(
Adafruit_BME280::MODE_NORMAL,
Adafruit_BME280::SAMPLING_X2,
Adafruit_BME280::SAMPLING_X16,
Adafruit_BME280::SAMPLING_X1,
Adafruit_BME280::FILTER_X4,
Adafruit_BME280::STANDBY_MS_500
);
return true;
}
bool Bme280Sensor::init_bmp280() {
if (_wire == nullptr) {
return false;
}
_bmp280 = new Adafruit_BMP280(_wire);
if (_bmp280 == nullptr) {
return false;
}
bool ok = _bmp280 -> begin(_config.i2c_address);
if (!ok) {
delete _bmp280;
_bmp280 = nullptr;
return false;
}
_bmp280 -> setSampling(
Adafruit_BMP280::MODE_NORMAL,
Adafruit_BMP280::SAMPLING_X2,
Adafruit_BMP280::SAMPLING_X16,
Adafruit_BMP280::FILTER_X4,
Adafruit_BMP280::STANDBY_MS_500
);
return true;
}
void Bme280Sensor::update_filtered_temperature(float value) {
if (!_has_valid_data || _filtered_temperature_c == 0.0f) {
_filtered_temperature_c = value;
return;
}
_filtered_temperature_c =
(_filtered_temperature_c * (1.0f - _config.temperature_ema_alpha)) +
(value * _config.temperature_ema_alpha);
}
void Bme280Sensor::update_filtered_pressure(float value) {
if (!_has_valid_data || _filtered_pressure_hpa == 0.0f) {
_filtered_pressure_hpa = value;
return;
}
_filtered_pressure_hpa =
(_filtered_pressure_hpa * (1.0f - _config.pressure_ema_alpha)) +
(value * _config.pressure_ema_alpha);
}
void Bme280Sensor::update_filtered_humidity(float value) {
if (!_has_valid_data || _filtered_humidity_percent == 0.0f) {
_filtered_humidity_percent = value;
return;
}
_filtered_humidity_percent =
(_filtered_humidity_percent * (1.0f - _config.humidity_ema_alpha)) +
(value * _config.humidity_ema_alpha);
}