diff --git a/esphome/components/ccs811/ccs811.cpp b/esphome/components/ccs811/ccs811.cpp index 8672c68ec8..4eba09ec47 100644 --- a/esphome/components/ccs811/ccs811.cpp +++ b/esphome/components/ccs811/ccs811.cpp @@ -82,6 +82,30 @@ void CCS811Component::update() { this->tvoc_->publish_state(tvoc); this->status_clear_warning(); + + this->send_env_data_(); +} +void CCS811Component::send_env_data_() { + if (this->humidity_ == nullptr && this->temperature_ == nullptr) + return; + + float humidity = NAN; + if (this->humidity_ != nullptr) + humidity = this->humidity_->state; + if (isnan(humidity) || humidity < 0 || humidity > 100) + humidity = 50; + float temperature = NAN; + if (this->temperature_ != nullptr) + temperature = this->temperature_->state; + if (isnan(temperature) || temperature < -25 || temperature > 50) + temperature = 25; + // temperature has a 25° offset to allow negative temperatures + temperature += 25; + + // only 0.5 fractions are supported (application note) + auto hum_value = static_cast(roundf(humidity * 2)); + auto temp_value = static_cast(roundf(temperature * 2)); + this->write_bytes(0x05, {hum_value, 0x00, temp_value, 0x00}); } void CCS811Component::dump_config() { ESP_LOGCONFIG(TAG, "CCS811"); diff --git a/esphome/components/ccs811/ccs811.h b/esphome/components/ccs811/ccs811.h index 7781cfd9a5..cea919c9a5 100644 --- a/esphome/components/ccs811/ccs811.h +++ b/esphome/components/ccs811/ccs811.h @@ -13,6 +13,8 @@ class CCS811Component : public PollingComponent, public i2c::I2CDevice { void set_co2(sensor::Sensor *co2) { co2_ = co2; } void set_tvoc(sensor::Sensor *tvoc) { tvoc_ = tvoc; } void set_baseline(uint16_t baseline) { baseline_ = baseline; } + void set_humidity(sensor::Sensor *humidity) { humidity_ = humidity; } + void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; } /// Setup the sensor and test for a connection. void setup() override; @@ -28,6 +30,7 @@ class CCS811Component : public PollingComponent, public i2c::I2CDevice { bool status_has_error_() { return this->read_status_().value_or(1) & 1; } bool status_app_is_valid_() { return this->read_status_().value_or(0) & (1 << 4); } bool status_has_data_() { return this->read_status_().value_or(0) & (1 << 3); } + void send_env_data_(); enum ErrorCode { UNKNOWN, @@ -41,6 +44,10 @@ class CCS811Component : public PollingComponent, public i2c::I2CDevice { sensor::Sensor *co2_{nullptr}; sensor::Sensor *tvoc_{nullptr}; optional baseline_{}; + /// Input sensor for humidity reading. + sensor::Sensor *humidity_{nullptr}; + /// Input sensor for temperature reading. + sensor::Sensor *temperature_{nullptr}; }; } // namespace ccs811 diff --git a/esphome/components/ccs811/sensor.py b/esphome/components/ccs811/sensor.py index 40bdd45303..ebc2b0e363 100644 --- a/esphome/components/ccs811/sensor.py +++ b/esphome/components/ccs811/sensor.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import CONF_ID, ICON_GAS_CYLINDER, ICON_RADIATOR, UNIT_PARTS_PER_MILLION, \ - UNIT_PARTS_PER_BILLION + UNIT_PARTS_PER_BILLION, CONF_TEMPERATURE, CONF_HUMIDITY DEPENDENCIES = ['i2c'] @@ -17,7 +17,10 @@ CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(CCS811Component), cv.Required(CONF_ECO2): sensor.sensor_schema(UNIT_PARTS_PER_MILLION, ICON_GAS_CYLINDER, 0), cv.Required(CONF_TVOC): sensor.sensor_schema(UNIT_PARTS_PER_BILLION, ICON_RADIATOR, 0), + cv.Optional(CONF_BASELINE): cv.hex_uint16_t, + cv.Optional(CONF_TEMPERATURE): cv.use_id(sensor.Sensor), + cv.Optional(CONF_HUMIDITY): cv.use_id(sensor.Sensor), }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x5A)) @@ -33,3 +36,10 @@ def to_code(config): if CONF_BASELINE in config: cg.add(var.set_baseline(config[CONF_BASELINE])) + + if CONF_TEMPERATURE in config: + sens = yield cg.get_variable(config[CONF_TEMPERATURE]) + cg.add(var.set_temperature(sens)) + if CONF_HUMIDITY in config: + sens = yield cg.get_variable(config[CONF_HUMIDITY]) + cg.add(var.set_humidity(sens))