mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Add min_save_interval to total_energy/integration for memory wear (#1665)
Co-authored-by: Andreas Hergert <andreas.hergert@otrs.com> Co-authored-by: Otto Winter <otto@otto-winter.com>
This commit is contained in:
		| @@ -16,6 +16,8 @@ void IntegrationSensor::setup() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   this->last_update_ = millis(); |   this->last_update_ = millis(); | ||||||
|  |   this->last_save_ = this->last_update_; | ||||||
|  |  | ||||||
|   this->publish_and_save_(this->result_); |   this->publish_and_save_(this->result_); | ||||||
|   this->sensor_->add_on_state_callback([this](float state) { this->process_sensor_value_(state); }); |   this->sensor_->add_on_state_callback([this](float state) { this->process_sensor_value_(state); }); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ class IntegrationSensor : public sensor::Sensor, public Component { | |||||||
|   void setup() override; |   void setup() override; | ||||||
|   void dump_config() override; |   void dump_config() override; | ||||||
|   float get_setup_priority() const override { return setup_priority::DATA; } |   float get_setup_priority() const override { return setup_priority::DATA; } | ||||||
|  |   void set_min_save_interval(uint32_t min_interval) { this->min_save_interval_ = min_interval; } | ||||||
|   void set_sensor(Sensor *sensor) { sensor_ = sensor; } |   void set_sensor(Sensor *sensor) { sensor_ = sensor; } | ||||||
|   void set_time(IntegrationSensorTime time) { time_ = time; } |   void set_time(IntegrationSensorTime time) { time_ = time; } | ||||||
|   void set_method(IntegrationMethod method) { method_ = method; } |   void set_method(IntegrationMethod method) { method_ = method; } | ||||||
| @@ -55,6 +56,10 @@ class IntegrationSensor : public sensor::Sensor, public Component { | |||||||
|     this->result_ = result; |     this->result_ = result; | ||||||
|     this->publish_state(result); |     this->publish_state(result); | ||||||
|     float result_f = result; |     float result_f = result; | ||||||
|  |     const uint32_t now = millis(); | ||||||
|  |     if (now - this->last_save_ < this->min_save_interval_) | ||||||
|  |       return; | ||||||
|  |     this->last_save_ = now; | ||||||
|     this->rtc_.save(&result_f); |     this->rtc_.save(&result_f); | ||||||
|   } |   } | ||||||
|   std::string unit_of_measurement() override; |   std::string unit_of_measurement() override; | ||||||
| @@ -67,6 +72,8 @@ class IntegrationSensor : public sensor::Sensor, public Component { | |||||||
|   bool restore_; |   bool restore_; | ||||||
|   ESPPreferenceObject rtc_; |   ESPPreferenceObject rtc_; | ||||||
|  |  | ||||||
|  |   uint32_t last_save_{0}; | ||||||
|  |   uint32_t min_save_interval_{0}; | ||||||
|   uint32_t last_update_; |   uint32_t last_update_; | ||||||
|   double result_{0.0f}; |   double result_{0.0f}; | ||||||
|   float last_value_{0.0f}; |   float last_value_{0.0f}; | ||||||
|   | |||||||
| @@ -27,6 +27,8 @@ INTEGRATION_METHODS = { | |||||||
|  |  | ||||||
| CONF_TIME_UNIT = "time_unit" | CONF_TIME_UNIT = "time_unit" | ||||||
| CONF_INTEGRATION_METHOD = "integration_method" | CONF_INTEGRATION_METHOD = "integration_method" | ||||||
|  | CONF_MIN_SAVE_INTERVAL = "min_save_interval" | ||||||
|  |  | ||||||
|  |  | ||||||
| CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend( | CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend( | ||||||
|     { |     { | ||||||
| @@ -37,6 +39,9 @@ CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend( | |||||||
|             INTEGRATION_METHODS, lower=True |             INTEGRATION_METHODS, lower=True | ||||||
|         ), |         ), | ||||||
|         cv.Optional(CONF_RESTORE, default=False): cv.boolean, |         cv.Optional(CONF_RESTORE, default=False): cv.boolean, | ||||||
|  |         cv.Optional( | ||||||
|  |             CONF_MIN_SAVE_INTERVAL, default="0s" | ||||||
|  |         ): cv.positive_time_period_milliseconds, | ||||||
|     } |     } | ||||||
| ).extend(cv.COMPONENT_SCHEMA) | ).extend(cv.COMPONENT_SCHEMA) | ||||||
|  |  | ||||||
| @@ -52,6 +57,7 @@ async def to_code(config): | |||||||
|     cg.add(var.set_time(config[CONF_TIME_UNIT])) |     cg.add(var.set_time(config[CONF_TIME_UNIT])) | ||||||
|     cg.add(var.set_method(config[CONF_INTEGRATION_METHOD])) |     cg.add(var.set_method(config[CONF_INTEGRATION_METHOD])) | ||||||
|     cg.add(var.set_restore(config[CONF_RESTORE])) |     cg.add(var.set_restore(config[CONF_RESTORE])) | ||||||
|  |     cg.add(var.set_min_save_interval(config[CONF_MIN_SAVE_INTERVAL])) | ||||||
|  |  | ||||||
|  |  | ||||||
| @automation.register_action( | @automation.register_action( | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ from esphome.const import ( | |||||||
| DEPENDENCIES = ["time"] | DEPENDENCIES = ["time"] | ||||||
|  |  | ||||||
| CONF_POWER_ID = "power_id" | CONF_POWER_ID = "power_id" | ||||||
|  | CONF_MIN_SAVE_INTERVAL = "min_save_interval" | ||||||
| total_daily_energy_ns = cg.esphome_ns.namespace("total_daily_energy") | total_daily_energy_ns = cg.esphome_ns.namespace("total_daily_energy") | ||||||
| TotalDailyEnergy = total_daily_energy_ns.class_( | TotalDailyEnergy = total_daily_energy_ns.class_( | ||||||
|     "TotalDailyEnergy", sensor.Sensor, cg.Component |     "TotalDailyEnergy", sensor.Sensor, cg.Component | ||||||
| @@ -29,6 +30,9 @@ CONFIG_SCHEMA = ( | |||||||
|             cv.GenerateID(): cv.declare_id(TotalDailyEnergy), |             cv.GenerateID(): cv.declare_id(TotalDailyEnergy), | ||||||
|             cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock), |             cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock), | ||||||
|             cv.Required(CONF_POWER_ID): cv.use_id(sensor.Sensor), |             cv.Required(CONF_POWER_ID): cv.use_id(sensor.Sensor), | ||||||
|  |             cv.Optional( | ||||||
|  |                 CONF_MIN_SAVE_INTERVAL, default="0s" | ||||||
|  |             ): cv.positive_time_period_milliseconds, | ||||||
|         } |         } | ||||||
|     ) |     ) | ||||||
|     .extend(cv.COMPONENT_SCHEMA) |     .extend(cv.COMPONENT_SCHEMA) | ||||||
| @@ -45,3 +49,4 @@ async def to_code(config): | |||||||
|     cg.add(var.set_parent(sens)) |     cg.add(var.set_parent(sens)) | ||||||
|     time_ = await cg.get_variable(config[CONF_TIME_ID]) |     time_ = await cg.get_variable(config[CONF_TIME_ID]) | ||||||
|     cg.add(var.set_time(time_)) |     cg.add(var.set_time(time_)) | ||||||
|  |     cg.add(var.set_min_save_interval(config[CONF_MIN_SAVE_INTERVAL])) | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ void TotalDailyEnergy::setup() { | |||||||
|     this->publish_state_and_save(0); |     this->publish_state_and_save(0); | ||||||
|   } |   } | ||||||
|   this->last_update_ = millis(); |   this->last_update_ = millis(); | ||||||
|  |   this->last_save_ = this->last_update_; | ||||||
|  |  | ||||||
|   this->parent_->add_on_state_callback([this](float state) { this->process_new_state_(state); }); |   this->parent_->add_on_state_callback([this](float state) { this->process_new_state_(state); }); | ||||||
| } | } | ||||||
| @@ -37,9 +38,14 @@ void TotalDailyEnergy::loop() { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| void TotalDailyEnergy::publish_state_and_save(float state) { | void TotalDailyEnergy::publish_state_and_save(float state) { | ||||||
|   this->pref_.save(&state); |  | ||||||
|   this->total_energy_ = state; |   this->total_energy_ = state; | ||||||
|   this->publish_state(state); |   this->publish_state(state); | ||||||
|  |   const uint32_t now = millis(); | ||||||
|  |   if (now - this->last_save_ < this->min_save_interval_) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   this->last_save_ = now; | ||||||
|  |   this->pref_.save(&state); | ||||||
| } | } | ||||||
| void TotalDailyEnergy::process_new_state_(float state) { | void TotalDailyEnergy::process_new_state_(float state) { | ||||||
|   if (isnan(state)) |   if (isnan(state)) | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ namespace total_daily_energy { | |||||||
|  |  | ||||||
| class TotalDailyEnergy : public sensor::Sensor, public Component { | class TotalDailyEnergy : public sensor::Sensor, public Component { | ||||||
|  public: |  public: | ||||||
|  |   void set_min_save_interval(uint32_t min_interval) { this->min_save_interval_ = min_interval; } | ||||||
|   void set_time(time::RealTimeClock *time) { time_ = time; } |   void set_time(time::RealTimeClock *time) { time_ = time; } | ||||||
|   void set_parent(Sensor *parent) { parent_ = parent; } |   void set_parent(Sensor *parent) { parent_ = parent; } | ||||||
|   void setup() override; |   void setup() override; | ||||||
| @@ -30,6 +31,8 @@ class TotalDailyEnergy : public sensor::Sensor, public Component { | |||||||
|   Sensor *parent_; |   Sensor *parent_; | ||||||
|   uint16_t last_day_of_year_{}; |   uint16_t last_day_of_year_{}; | ||||||
|   uint32_t last_update_{0}; |   uint32_t last_update_{0}; | ||||||
|  |   uint32_t last_save_{0}; | ||||||
|  |   uint32_t min_save_interval_{0}; | ||||||
|   float total_energy_{0.0f}; |   float total_energy_{0.0f}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -540,6 +540,11 @@ sensor: | |||||||
|     sensor: hlw8012_power |     sensor: hlw8012_power | ||||||
|     name: 'Integration Sensor' |     name: 'Integration Sensor' | ||||||
|     time_unit: s |     time_unit: s | ||||||
|  |   - platform: integration | ||||||
|  |     sensor: hlw8012_power | ||||||
|  |     name: 'Integration Sensor lazy' | ||||||
|  |     time_unit: s | ||||||
|  |     min_save_interval: 60s | ||||||
|   - platform: hmc5883l |   - platform: hmc5883l | ||||||
|     address: 0x68 |     address: 0x68 | ||||||
|     field_strength_x: |     field_strength_x: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user