mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	extend scd4x (#3409)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -168,7 +168,7 @@ esphome/components/rf_bridge/* @jesserockz | ||||
| esphome/components/rgbct/* @jesserockz | ||||
| esphome/components/rtttl/* @glmnet | ||||
| esphome/components/safe_mode/* @jsuanet @paulmonigatti | ||||
| esphome/components/scd4x/* @sjtrny | ||||
| esphome/components/scd4x/* @martgras @sjtrny | ||||
| esphome/components/script/* @esphome/core | ||||
| esphome/components/sdm_meter/* @jesserockz @polyfaces | ||||
| esphome/components/sdp3x/* @Azimath | ||||
|   | ||||
							
								
								
									
										28
									
								
								esphome/components/scd4x/automation.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								esphome/components/scd4x/automation.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/automation.h" | ||||
| #include "scd4x.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace scd4x { | ||||
|  | ||||
| template<typename... Ts> class PerformForcedCalibrationAction : public Action<Ts...>, public Parented<SCD4XComponent> { | ||||
|  public: | ||||
|   void play(Ts... x) override { | ||||
|     if (this->value_.has_value()) { | ||||
|       this->parent_->perform_forced_calibration(value_.value()); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   TEMPLATABLE_VALUE(uint16_t, value) | ||||
| }; | ||||
|  | ||||
| template<typename... Ts> class FactoryResetAction : public Action<Ts...>, public Parented<SCD4XComponent> { | ||||
|  public: | ||||
|   void play(Ts... x) override { this->parent_->factory_reset(); } | ||||
| }; | ||||
|  | ||||
| }  // namespace scd4x | ||||
| }  // namespace esphome | ||||
| @@ -13,29 +13,24 @@ static const uint16_t SCD4X_CMD_ALTITUDE_COMPENSATION = 0x2427; | ||||
| static const uint16_t SCD4X_CMD_AMBIENT_PRESSURE_COMPENSATION = 0xe000; | ||||
| static const uint16_t SCD4X_CMD_AUTOMATIC_SELF_CALIBRATION = 0x2416; | ||||
| static const uint16_t SCD4X_CMD_START_CONTINUOUS_MEASUREMENTS = 0x21b1; | ||||
| static const uint16_t SCD4X_CMD_START_LOW_POWER_CONTINUOUS_MEASUREMENTS = 0x21ac; | ||||
| static const uint16_t SCD4X_CMD_START_LOW_POWER_SINGLE_SHOT = 0x219d;  // SCD41 only | ||||
| static const uint16_t SCD4X_CMD_START_LOW_POWER_SINGLE_SHOT_RHT_ONLY = 0x2196; | ||||
| static const uint16_t SCD4X_CMD_GET_DATA_READY_STATUS = 0xe4b8; | ||||
| static const uint16_t SCD4X_CMD_READ_MEASUREMENT = 0xec05; | ||||
| static const uint16_t SCD4X_CMD_PERFORM_FORCED_CALIBRATION = 0x362f; | ||||
| static const uint16_t SCD4X_CMD_STOP_MEASUREMENTS = 0x3f86; | ||||
|  | ||||
| static const uint16_t SCD4X_CMD_FACTORY_RESET = 0x3632; | ||||
| static const uint16_t SCD4X_CMD_GET_FEATURESET = 0x202f; | ||||
| static const float SCD4X_TEMPERATURE_OFFSET_MULTIPLIER = (1 << 16) / 175.0f; | ||||
| static const uint16_t SCD41_ID = 0x1408; | ||||
| static const uint16_t SCD40_ID = 0x440; | ||||
|  | ||||
| void SCD4XComponent::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up scd4x..."); | ||||
|  | ||||
|   // the sensor needs 1000 ms to enter the idle state | ||||
|   this->set_timeout(1000, [this]() { | ||||
|     uint16_t raw_read_status; | ||||
|     if (!this->get_register(SCD4X_CMD_GET_DATA_READY_STATUS, raw_read_status)) { | ||||
|       ESP_LOGE(TAG, "Failed to read data ready status"); | ||||
|       this->mark_failed(); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     uint32_t stop_measurement_delay = 0; | ||||
|     // In order to query the device periodic measurement must be ceased | ||||
|     if (raw_read_status) { | ||||
|       ESP_LOGD(TAG, "Sensor has data available, stopping periodic measurement"); | ||||
|     this->status_clear_error(); | ||||
|     if (!this->write_command(SCD4X_CMD_STOP_MEASUREMENTS)) { | ||||
|       ESP_LOGE(TAG, "Failed to stop measurements"); | ||||
|       this->mark_failed(); | ||||
| @@ -43,9 +38,7 @@ void SCD4XComponent::setup() { | ||||
|     } | ||||
|     // According to the SCD4x datasheet the sensor will only respond to other commands after waiting 500 ms after | ||||
|     // issuing the stop_periodic_measurement command | ||||
|       stop_measurement_delay = 500; | ||||
|     } | ||||
|     this->set_timeout(stop_measurement_delay, [this]() { | ||||
|     this->set_timeout(500, [this]() { | ||||
|       uint16_t raw_serial_number[3]; | ||||
|       if (!this->get_register(SCD4X_CMD_GET_SERIAL_NUMBER, raw_serial_number, 3, 1)) { | ||||
|         ESP_LOGE(TAG, "Failed to read serial number"); | ||||
| @@ -89,15 +82,9 @@ void SCD4XComponent::setup() { | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       // Finally start sensor measurements | ||||
|       if (!this->write_command(SCD4X_CMD_START_CONTINUOUS_MEASUREMENTS)) { | ||||
|         ESP_LOGE(TAG, "Error starting continuous measurements."); | ||||
|         this->error_code_ = MEASUREMENT_INIT_FAILED; | ||||
|         this->mark_failed(); | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       initialized_ = true; | ||||
|       // Finally start sensor measurements | ||||
|       this->start_measurement_(); | ||||
|       ESP_LOGD(TAG, "Sensor initialized"); | ||||
|     }); | ||||
|   }); | ||||
| @@ -123,6 +110,10 @@ void SCD4XComponent::dump_config() { | ||||
|     } | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, "  Automatic self calibration: %s", ONOFF(this->enable_asc_)); | ||||
|   if (this->ambient_pressure_source_ != nullptr) { | ||||
|     ESP_LOGCONFIG(TAG, "  Dynamic ambient pressure compensation using sensor '%s'", | ||||
|                   this->ambient_pressure_source_->get_name().c_str()); | ||||
|   } else { | ||||
|     if (this->ambient_pressure_compensation_) { | ||||
|       ESP_LOGCONFIG(TAG, "  Altitude compensation disabled"); | ||||
|       ESP_LOGCONFIG(TAG, "  Ambient pressure compensation: %dmBar", this->ambient_pressure_); | ||||
| @@ -130,6 +121,21 @@ void SCD4XComponent::dump_config() { | ||||
|       ESP_LOGCONFIG(TAG, "  Ambient pressure compensation disabled"); | ||||
|       ESP_LOGCONFIG(TAG, "  Altitude compensation: %dm", this->altitude_compensation_); | ||||
|     } | ||||
|   } | ||||
|   switch (this->measurement_mode_) { | ||||
|     case PERIODIC: | ||||
|       ESP_LOGCONFIG(TAG, "  Measurement mode: periodic (5s)"); | ||||
|       break; | ||||
|     case LOW_POWER_PERIODIC: | ||||
|       ESP_LOGCONFIG(TAG, "  Measurement mode: low power periodic (30s)"); | ||||
|       break; | ||||
|     case SINGLE_SHOT: | ||||
|       ESP_LOGCONFIG(TAG, "  Measurement mode: single shot"); | ||||
|       break; | ||||
|     case SINGLE_SHOT_RHT_ONLY: | ||||
|       ESP_LOGCONFIG(TAG, "  Measurement mode: single shot rht only"); | ||||
|       break; | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, "  Temperature offset: %.2f °C", this->temperature_offset_); | ||||
|   LOG_UPDATE_INTERVAL(this); | ||||
|   LOG_SENSOR("  ", "CO2", this->co2_sensor_); | ||||
| @@ -149,6 +155,13 @@ void SCD4XComponent::update() { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   uint32_t wait_time = 0; | ||||
|   if (this->measurement_mode_ == SINGLE_SHOT || this->measurement_mode_ == SINGLE_SHOT_RHT_ONLY) { | ||||
|     start_measurement_(); | ||||
|     wait_time = | ||||
|         this->measurement_mode_ == SINGLE_SHOT ? 5000 : 50;  // Single shot measurement takes 5 secs rht mode 50 ms | ||||
|   } | ||||
|   this->set_timeout(wait_time, [this]() { | ||||
|     // Check if data is ready | ||||
|     if (!this->write_command(SCD4X_CMD_GET_DATA_READY_STATUS)) { | ||||
|       this->status_set_warning(); | ||||
| @@ -156,6 +169,7 @@ void SCD4XComponent::update() { | ||||
|     } | ||||
|  | ||||
|     uint16_t raw_read_status; | ||||
|  | ||||
|     if (!this->read_data(raw_read_status) || raw_read_status == 0x00) { | ||||
|       this->status_set_warning(); | ||||
|       ESP_LOGW(TAG, "Data not ready yet!"); | ||||
| @@ -165,16 +179,14 @@ void SCD4XComponent::update() { | ||||
|     if (!this->write_command(SCD4X_CMD_READ_MEASUREMENT)) { | ||||
|       ESP_LOGW(TAG, "Error reading measurement!"); | ||||
|       this->status_set_warning(); | ||||
|     return; | ||||
|       return;  // NO RETRY | ||||
|     } | ||||
|  | ||||
|     // Read off sensor data | ||||
|     uint16_t raw_data[3]; | ||||
|     if (!this->read_data(raw_data, 3)) { | ||||
|       this->status_set_warning(); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (this->co2_sensor_ != nullptr) | ||||
|       this->co2_sensor_->publish_state(raw_data[0]); | ||||
|  | ||||
| @@ -182,14 +194,66 @@ void SCD4XComponent::update() { | ||||
|       const float temperature = -45.0f + (175.0f * (raw_data[1])) / (1 << 16); | ||||
|       this->temperature_sensor_->publish_state(temperature); | ||||
|     } | ||||
|  | ||||
|     if (this->humidity_sensor_ != nullptr) { | ||||
|       const float humidity = (100.0f * raw_data[2]) / (1 << 16); | ||||
|       this->humidity_sensor_->publish_state(humidity); | ||||
|     } | ||||
|  | ||||
|     this->status_clear_warning(); | ||||
|   });  // set_timeout | ||||
| } | ||||
|  | ||||
| bool SCD4XComponent::perform_forced_calibration(uint16_t current_co2_concentration) { | ||||
|   /* | ||||
|     Operate the SCD4x in the operation mode later used in normal sensor operation (periodic measurement, low power | ||||
|     periodic measurement or single shot) for > 3 minutes in an environment with homogenous and constant CO2 | ||||
|     concentration before performing a forced recalibration. | ||||
|   */ | ||||
|   if (!this->write_command(SCD4X_CMD_STOP_MEASUREMENTS)) { | ||||
|     ESP_LOGE(TAG, "Failed to stop measurements"); | ||||
|     this->status_set_warning(); | ||||
|   } | ||||
|   this->set_timeout(500, [this, current_co2_concentration]() { | ||||
|     if (this->write_command(SCD4X_CMD_PERFORM_FORCED_CALIBRATION, current_co2_concentration)) { | ||||
|       ESP_LOGD(TAG, "setting forced calibration Co2 level %d ppm", current_co2_concentration); | ||||
|       // frc takes 400 ms | ||||
|       // because this method will be used very rarly | ||||
|       // the simple aproach with delay is ok | ||||
|       delay(400);  // NOLINT' | ||||
|       if (!this->start_measurement_()) { | ||||
|         return false; | ||||
|       } else { | ||||
|         ESP_LOGD(TAG, "forced calibration complete"); | ||||
|       } | ||||
|       return true; | ||||
|     } else { | ||||
|       ESP_LOGE(TAG, "force calibration failed"); | ||||
|       this->error_code_ = FRC_FAILED; | ||||
|       this->status_set_warning(); | ||||
|       return false; | ||||
|     } | ||||
|   }); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool SCD4XComponent::factory_reset() { | ||||
|   if (!this->write_command(SCD4X_CMD_STOP_MEASUREMENTS)) { | ||||
|     ESP_LOGE(TAG, "Failed to stop measurements"); | ||||
|     this->status_set_warning(); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   this->set_timeout(500, [this]() { | ||||
|     if (!this->write_command(SCD4X_CMD_FACTORY_RESET)) { | ||||
|       ESP_LOGE(TAG, "Failed to send factory reset command"); | ||||
|       this->status_set_warning(); | ||||
|       return false; | ||||
|     } | ||||
|     ESP_LOGD(TAG, "Factory reset complete"); | ||||
|     return true; | ||||
|   }); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| // Note pressure in bar here. Convert to hPa | ||||
| void SCD4XComponent::set_ambient_pressure_compensation(float pressure_in_bar) { | ||||
|   ambient_pressure_compensation_ = true; | ||||
| @@ -213,5 +277,38 @@ bool SCD4XComponent::update_ambient_pressure_compensation_(uint16_t pressure_in_ | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool SCD4XComponent::start_measurement_() { | ||||
|   uint16_t measurement_command = SCD4X_CMD_START_CONTINUOUS_MEASUREMENTS; | ||||
|   switch (this->measurement_mode_) { | ||||
|     case PERIODIC: | ||||
|       measurement_command = SCD4X_CMD_START_CONTINUOUS_MEASUREMENTS; | ||||
|       break; | ||||
|     case LOW_POWER_PERIODIC: | ||||
|       measurement_command = SCD4X_CMD_START_LOW_POWER_CONTINUOUS_MEASUREMENTS; | ||||
|       break; | ||||
|     case SINGLE_SHOT: | ||||
|       measurement_command = SCD4X_CMD_START_LOW_POWER_SINGLE_SHOT; | ||||
|       break; | ||||
|     case SINGLE_SHOT_RHT_ONLY: | ||||
|       measurement_command = SCD4X_CMD_START_LOW_POWER_SINGLE_SHOT_RHT_ONLY; | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   static uint8_t remaining_retries = 3; | ||||
|   while (remaining_retries) { | ||||
|     if (!this->write_command(measurement_command)) { | ||||
|       ESP_LOGE(TAG, "Error starting measurements."); | ||||
|       this->error_code_ = MEASUREMENT_INIT_FAILED; | ||||
|       this->status_set_warning(); | ||||
|       if (--remaining_retries == 0) | ||||
|         return false; | ||||
|       delay(50);  // NOLINT wait 50 ms and try again | ||||
|     } | ||||
|     this->status_clear_warning(); | ||||
|     return true; | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| }  // namespace scd4x | ||||
| }  // namespace esphome | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <vector> | ||||
| #include "esphome/core/application.h" | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/components/sensor/sensor.h" | ||||
| #include "esphome/components/sensirion_common/i2c_sensirion.h" | ||||
| @@ -7,7 +8,14 @@ | ||||
| namespace esphome { | ||||
| namespace scd4x { | ||||
|  | ||||
| enum ERRORCODE { COMMUNICATION_FAILED, SERIAL_NUMBER_IDENTIFICATION_FAILED, MEASUREMENT_INIT_FAILED, UNKNOWN }; | ||||
| enum ERRORCODE { | ||||
|   COMMUNICATION_FAILED, | ||||
|   SERIAL_NUMBER_IDENTIFICATION_FAILED, | ||||
|   MEASUREMENT_INIT_FAILED, | ||||
|   FRC_FAILED, | ||||
|   UNKNOWN | ||||
| }; | ||||
| enum MeasurementMode { PERIODIC, LOW_POWER_PERIODIC, SINGLE_SHOT, SINGLE_SHOT_RHT_ONLY }; | ||||
|  | ||||
| class SCD4XComponent : public PollingComponent, public sensirion_common::SensirionI2CDevice { | ||||
|  public: | ||||
| @@ -25,10 +33,13 @@ class SCD4XComponent : public PollingComponent, public sensirion_common::Sensiri | ||||
|   void set_co2_sensor(sensor::Sensor *co2) { co2_sensor_ = co2; } | ||||
|   void set_temperature_sensor(sensor::Sensor *temperature) { temperature_sensor_ = temperature; }; | ||||
|   void set_humidity_sensor(sensor::Sensor *humidity) { humidity_sensor_ = humidity; } | ||||
|   void set_measurement_mode(MeasurementMode mode) { measurement_mode_ = mode; } | ||||
|   bool perform_forced_calibration(uint16_t current_co2_concentration); | ||||
|   bool factory_reset(); | ||||
|  | ||||
|  protected: | ||||
|   bool update_ambient_pressure_compensation_(uint16_t pressure_in_hpa); | ||||
|  | ||||
|   bool start_measurement_(); | ||||
|   ERRORCODE error_code_; | ||||
|  | ||||
|   bool initialized_{false}; | ||||
| @@ -38,7 +49,7 @@ class SCD4XComponent : public PollingComponent, public sensirion_common::Sensiri | ||||
|   bool ambient_pressure_compensation_; | ||||
|   uint16_t ambient_pressure_; | ||||
|   bool enable_asc_; | ||||
|  | ||||
|   MeasurementMode measurement_mode_{PERIODIC}; | ||||
|   sensor::Sensor *co2_sensor_{nullptr}; | ||||
|   sensor::Sensor *temperature_sensor_{nullptr}; | ||||
|   sensor::Sensor *humidity_sensor_{nullptr}; | ||||
|   | ||||
| @@ -2,11 +2,15 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.components import sensirion_common | ||||
| from esphome import automation | ||||
| from esphome.automation import maybe_simple_id | ||||
|  | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_CO2, | ||||
|     CONF_HUMIDITY, | ||||
|     CONF_TEMPERATURE, | ||||
|     CONF_VALUE, | ||||
|     DEVICE_CLASS_CARBON_DIOXIDE, | ||||
|     DEVICE_CLASS_HUMIDITY, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
| @@ -19,7 +23,7 @@ from esphome.const import ( | ||||
|     UNIT_PERCENT, | ||||
| ) | ||||
|  | ||||
| CODEOWNERS = ["@sjtrny"] | ||||
| CODEOWNERS = ["@sjtrny", "@martgras"] | ||||
| DEPENDENCIES = ["i2c"] | ||||
| AUTO_LOAD = ["sensirion_common"] | ||||
|  | ||||
| @@ -27,12 +31,29 @@ scd4x_ns = cg.esphome_ns.namespace("scd4x") | ||||
| SCD4XComponent = scd4x_ns.class_( | ||||
|     "SCD4XComponent", cg.PollingComponent, sensirion_common.SensirionI2CDevice | ||||
| ) | ||||
| MeasurementMode = scd4x_ns.enum("MEASUREMENT_MODE") | ||||
| MEASUREMENT_MODE_OPTIONS = { | ||||
|     "periodic": MeasurementMode.PERIODIC, | ||||
|     "low_power_periodic": MeasurementMode.LOW_POWER_PERIODIC, | ||||
|     "single_shot": MeasurementMode.SINGLE_SHOT, | ||||
|     "single_shot_rht_only": MeasurementMode.SINGLE_SHOT_RHT_ONLY, | ||||
| } | ||||
|  | ||||
|  | ||||
| # Actions | ||||
| PerformForcedCalibrationAction = scd4x_ns.class_( | ||||
|     "PerformForcedCalibrationAction", automation.Action | ||||
| ) | ||||
| FactoryResetAction = scd4x_ns.class_("FactoryResetAction", automation.Action) | ||||
|  | ||||
|  | ||||
| CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration" | ||||
| CONF_ALTITUDE_COMPENSATION = "altitude_compensation" | ||||
| CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation" | ||||
| CONF_TEMPERATURE_OFFSET = "temperature_offset" | ||||
| CONF_AMBIENT_PRESSURE_COMPENSATION_SOURCE = "ambient_pressure_compensation_source" | ||||
| CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration" | ||||
| CONF_MEASUREMENT_MODE = "measurement_mode" | ||||
| CONF_TEMPERATURE_OFFSET = "temperature_offset" | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
| @@ -69,6 +90,9 @@ CONFIG_SCHEMA = ( | ||||
|             cv.Optional(CONF_AMBIENT_PRESSURE_COMPENSATION_SOURCE): cv.use_id( | ||||
|                 sensor.Sensor | ||||
|             ), | ||||
|             cv.Optional(CONF_MEASUREMENT_MODE, default="periodic"): cv.enum( | ||||
|                 MEASUREMENT_MODE_OPTIONS, lower=True | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
| @@ -106,3 +130,42 @@ async def to_code(config): | ||||
|     if CONF_AMBIENT_PRESSURE_COMPENSATION_SOURCE in config: | ||||
|         sens = await cg.get_variable(config[CONF_AMBIENT_PRESSURE_COMPENSATION_SOURCE]) | ||||
|         cg.add(var.set_ambient_pressure_source(sens)) | ||||
|  | ||||
|     cg.add(var.set_measurement_mode(config[CONF_MEASUREMENT_MODE])) | ||||
|  | ||||
|  | ||||
| SCD4X_ACTION_SCHEMA = maybe_simple_id( | ||||
|     { | ||||
|         cv.GenerateID(): cv.use_id(SCD4XComponent), | ||||
|         cv.Required(CONF_VALUE): cv.templatable(cv.positive_int), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_action( | ||||
|     "scd4x.perform_forced_calibration", | ||||
|     PerformForcedCalibrationAction, | ||||
|     SCD4X_ACTION_SCHEMA, | ||||
| ) | ||||
| async def scd4x_frc_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     await cg.register_parented(var, config[CONF_ID]) | ||||
|     template_ = await cg.templatable(config[CONF_VALUE], args, cg.uint16) | ||||
|     cg.add(var.set_value(template_)) | ||||
|     return var | ||||
|  | ||||
|  | ||||
| SCD4X_RESET_ACTION_SCHEMA = maybe_simple_id( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.use_id(SCD4XComponent), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_action( | ||||
|     "scd4x.factory_reset", FactoryResetAction, SCD4X_RESET_ACTION_SCHEMA | ||||
| ) | ||||
| async def scd4x_reset_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     await cg.register_parented(var, config[CONF_ID]) | ||||
|     return var | ||||
|   | ||||
| @@ -890,6 +890,7 @@ sensor: | ||||
|     temperature_offset: 4.2C | ||||
|     i2c_id: i2c_bus | ||||
|   - platform: scd4x | ||||
|     id: scd40 | ||||
|     co2: | ||||
|       name: "SCD4X CO2" | ||||
|     temperature: | ||||
| @@ -2822,3 +2823,14 @@ lock: | ||||
|   - platform: copy | ||||
|     source_id: test_lock2 | ||||
|     name: Generic Output Lock Copy | ||||
|  | ||||
| button: | ||||
|   - platform: template | ||||
|     name: "Start calibration" | ||||
|     on_press: | ||||
|       - scd4x.perform_forced_calibration: | ||||
|           value: 419 | ||||
|           id: scd40 | ||||
|       - scd4x.factory_reset: | ||||
|           id: scd40 | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user