mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Merge branch 'api_conditional_memory' into integration
This commit is contained in:
		| @@ -28,19 +28,24 @@ static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_11; | |||||||
| #endif | #endif | ||||||
| #endif  // USE_ESP32 | #endif  // USE_ESP32 | ||||||
|  |  | ||||||
| enum class SamplingMode : uint8_t { AVG = 0, MIN = 1, MAX = 2 }; | enum class SamplingMode : uint8_t { | ||||||
|  |   AVG = 0, | ||||||
|  |   MIN = 1, | ||||||
|  |   MAX = 2, | ||||||
|  | }; | ||||||
|  |  | ||||||
| const LogString *sampling_mode_to_str(SamplingMode mode); | const LogString *sampling_mode_to_str(SamplingMode mode); | ||||||
|  |  | ||||||
| class Aggregator { | class Aggregator { | ||||||
|  public: |  public: | ||||||
|  |   Aggregator(SamplingMode mode); | ||||||
|   void add_sample(uint32_t value); |   void add_sample(uint32_t value); | ||||||
|   uint32_t aggregate(); |   uint32_t aggregate(); | ||||||
|   Aggregator(SamplingMode mode); |  | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   SamplingMode mode_{SamplingMode::AVG}; |  | ||||||
|   uint32_t aggr_{0}; |   uint32_t aggr_{0}; | ||||||
|   uint32_t samples_{0}; |   uint32_t samples_{0}; | ||||||
|  |   SamplingMode mode_{SamplingMode::AVG}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler { | class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler { | ||||||
| @@ -81,9 +86,9 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage | |||||||
| #endif  // USE_RP2040 | #endif  // USE_RP2040 | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   InternalGPIOPin *pin_; |  | ||||||
|   bool output_raw_{false}; |  | ||||||
|   uint8_t sample_count_{1}; |   uint8_t sample_count_{1}; | ||||||
|  |   bool output_raw_{false}; | ||||||
|  |   InternalGPIOPin *pin_; | ||||||
|   SamplingMode sampling_mode_{SamplingMode::AVG}; |   SamplingMode sampling_mode_{SamplingMode::AVG}; | ||||||
|  |  | ||||||
| #ifdef USE_RP2040 | #ifdef USE_RP2040 | ||||||
|   | |||||||
| @@ -61,7 +61,7 @@ uint32_t Aggregator::aggregate() { | |||||||
|  |  | ||||||
| void ADCSensor::update() { | void ADCSensor::update() { | ||||||
|   float value_v = this->sample(); |   float value_v = this->sample(); | ||||||
|   ESP_LOGV(TAG, "'%s': Got voltage=%.4fV", this->get_name().c_str(), value_v); |   ESP_LOGV(TAG, "'%s': Voltage=%.4fV", this->get_name().c_str(), value_v); | ||||||
|   this->publish_state(value_v); |   this->publish_state(value_v); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -55,32 +55,40 @@ void ADCSensor::setup() { | |||||||
| } | } | ||||||
|  |  | ||||||
| void ADCSensor::dump_config() { | void ADCSensor::dump_config() { | ||||||
|  |   static const char *const ATTEN_AUTO_STR = "auto"; | ||||||
|  |   static const char *const ATTEN_0DB_STR = "0 db"; | ||||||
|  |   static const char *const ATTEN_2_5DB_STR = "2.5 db"; | ||||||
|  |   static const char *const ATTEN_6DB_STR = "6 db"; | ||||||
|  |   static const char *const ATTEN_12DB_STR = "12 db"; | ||||||
|  |   const char *atten_str = ATTEN_AUTO_STR; | ||||||
|  |  | ||||||
|   LOG_SENSOR("", "ADC Sensor", this); |   LOG_SENSOR("", "ADC Sensor", this); | ||||||
|   LOG_PIN("  Pin: ", this->pin_); |   LOG_PIN("  Pin: ", this->pin_); | ||||||
|   if (this->autorange_) { |  | ||||||
|     ESP_LOGCONFIG(TAG, "  Attenuation: auto"); |   if (!this->autorange_) { | ||||||
|   } else { |  | ||||||
|     switch (this->attenuation_) { |     switch (this->attenuation_) { | ||||||
|       case ADC_ATTEN_DB_0: |       case ADC_ATTEN_DB_0: | ||||||
|         ESP_LOGCONFIG(TAG, "  Attenuation: 0db"); |         atten_str = ATTEN_0DB_STR; | ||||||
|         break; |         break; | ||||||
|       case ADC_ATTEN_DB_2_5: |       case ADC_ATTEN_DB_2_5: | ||||||
|         ESP_LOGCONFIG(TAG, "  Attenuation: 2.5db"); |         atten_str = ATTEN_2_5DB_STR; | ||||||
|         break; |         break; | ||||||
|       case ADC_ATTEN_DB_6: |       case ADC_ATTEN_DB_6: | ||||||
|         ESP_LOGCONFIG(TAG, "  Attenuation: 6db"); |         atten_str = ATTEN_6DB_STR; | ||||||
|         break; |         break; | ||||||
|       case ADC_ATTEN_DB_12_COMPAT: |       case ADC_ATTEN_DB_12_COMPAT: | ||||||
|         ESP_LOGCONFIG(TAG, "  Attenuation: 12db"); |         atten_str = ATTEN_12DB_STR; | ||||||
|         break; |         break; | ||||||
|       default:  // This is to satisfy the unused ADC_ATTEN_MAX |       default:  // This is to satisfy the unused ADC_ATTEN_MAX | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   ESP_LOGCONFIG(TAG, |   ESP_LOGCONFIG(TAG, | ||||||
|  |                 "  Attenuation: %s\n" | ||||||
|                 "  Samples: %i\n" |                 "  Samples: %i\n" | ||||||
|                 "  Sampling mode: %s", |                 "  Sampling mode: %s", | ||||||
|                 this->sample_count_, LOG_STR_ARG(sampling_mode_to_str(this->sampling_mode_))); |                 atten_str, this->sample_count_, LOG_STR_ARG(sampling_mode_to_str(this->sampling_mode_))); | ||||||
|   LOG_UPDATE_INTERVAL(this); |   LOG_UPDATE_INTERVAL(this); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -135,7 +135,9 @@ async def to_code(config): | |||||||
|     cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) |     cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) | ||||||
|     cg.add(var.set_batch_delay(config[CONF_BATCH_DELAY])) |     cg.add(var.set_batch_delay(config[CONF_BATCH_DELAY])) | ||||||
|  |  | ||||||
|     for conf in config.get(CONF_ACTIONS, []): |     if actions := config.get(CONF_ACTIONS, []): | ||||||
|  |         cg.add_define("USE_API_YAML_SERVICES") | ||||||
|  |         for conf in actions: | ||||||
|             template_args = [] |             template_args = [] | ||||||
|             func_args = [] |             func_args = [] | ||||||
|             service_arg_names = [] |             service_arg_names = [] | ||||||
| @@ -152,6 +154,7 @@ async def to_code(config): | |||||||
|             await automation.build_automation(trigger, func_args, conf) |             await automation.build_automation(trigger, func_args, conf) | ||||||
|  |  | ||||||
|     if CONF_ON_CLIENT_CONNECTED in config: |     if CONF_ON_CLIENT_CONNECTED in config: | ||||||
|  |         cg.add_define("USE_API_CLIENT_CONNECTED_TRIGGER") | ||||||
|         await automation.build_automation( |         await automation.build_automation( | ||||||
|             var.get_client_connected_trigger(), |             var.get_client_connected_trigger(), | ||||||
|             [(cg.std_string, "client_info"), (cg.std_string, "client_address")], |             [(cg.std_string, "client_info"), (cg.std_string, "client_address")], | ||||||
| @@ -159,6 +162,7 @@ async def to_code(config): | |||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     if CONF_ON_CLIENT_DISCONNECTED in config: |     if CONF_ON_CLIENT_DISCONNECTED in config: | ||||||
|  |         cg.add_define("USE_API_CLIENT_DISCONNECTED_TRIGGER") | ||||||
|         await automation.build_automation( |         await automation.build_automation( | ||||||
|             var.get_client_disconnected_trigger(), |             var.get_client_disconnected_trigger(), | ||||||
|             [(cg.std_string, "client_info"), (cg.std_string, "client_address")], |             [(cg.std_string, "client_info"), (cg.std_string, "client_address")], | ||||||
|   | |||||||
| @@ -1511,7 +1511,9 @@ ConnectResponse APIConnection::connect(const ConnectRequest &msg) { | |||||||
|   if (correct) { |   if (correct) { | ||||||
|     ESP_LOGD(TAG, "%s connected", this->get_client_combined_info().c_str()); |     ESP_LOGD(TAG, "%s connected", this->get_client_combined_info().c_str()); | ||||||
|     this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::AUTHENTICATED); |     this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::AUTHENTICATED); | ||||||
|  | #ifdef USE_API_CLIENT_CONNECTED_TRIGGER | ||||||
|     this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->client_peername_); |     this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->client_peername_); | ||||||
|  | #endif | ||||||
| #ifdef USE_HOMEASSISTANT_TIME | #ifdef USE_HOMEASSISTANT_TIME | ||||||
|     if (homeassistant::global_homeassistant_time != nullptr) { |     if (homeassistant::global_homeassistant_time != nullptr) { | ||||||
|       this->send_time_request(); |       this->send_time_request(); | ||||||
|   | |||||||
| @@ -184,7 +184,9 @@ void APIServer::loop() { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Rare case: handle disconnection |     // Rare case: handle disconnection | ||||||
|  | #ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER | ||||||
|     this->client_disconnected_trigger_->trigger(client->client_info_, client->client_peername_); |     this->client_disconnected_trigger_->trigger(client->client_info_, client->client_peername_); | ||||||
|  | #endif | ||||||
|     ESP_LOGV(TAG, "Remove connection %s", client->client_info_.c_str()); |     ESP_LOGV(TAG, "Remove connection %s", client->client_info_.c_str()); | ||||||
|  |  | ||||||
|     // Swap with the last element and pop (avoids expensive vector shifts) |     // Swap with the last element and pop (avoids expensive vector shifts) | ||||||
|   | |||||||
| @@ -105,7 +105,18 @@ class APIServer : public Component, public Controller { | |||||||
|   void on_media_player_update(media_player::MediaPlayer *obj) override; |   void on_media_player_update(media_player::MediaPlayer *obj) override; | ||||||
| #endif | #endif | ||||||
|   void send_homeassistant_service_call(const HomeassistantServiceResponse &call); |   void send_homeassistant_service_call(const HomeassistantServiceResponse &call); | ||||||
|   void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); } |   void register_user_service(UserServiceDescriptor *descriptor) { | ||||||
|  | #ifdef USE_API_YAML_SERVICES | ||||||
|  |     // Vector is pre-allocated when services are defined in YAML | ||||||
|  |     this->user_services_.push_back(descriptor); | ||||||
|  | #else | ||||||
|  |     // Lazy allocate vector on first use for CustomAPIDevice | ||||||
|  |     if (!this->user_services_) { | ||||||
|  |       this->user_services_ = std::make_unique<std::vector<UserServiceDescriptor *>>(); | ||||||
|  |     } | ||||||
|  |     this->user_services_->push_back(descriptor); | ||||||
|  | #endif | ||||||
|  |   } | ||||||
| #ifdef USE_HOMEASSISTANT_TIME | #ifdef USE_HOMEASSISTANT_TIME | ||||||
|   void request_time(); |   void request_time(); | ||||||
| #endif | #endif | ||||||
| @@ -134,19 +145,34 @@ class APIServer : public Component, public Controller { | |||||||
|   void get_home_assistant_state(std::string entity_id, optional<std::string> attribute, |   void get_home_assistant_state(std::string entity_id, optional<std::string> attribute, | ||||||
|                                 std::function<void(std::string)> f); |                                 std::function<void(std::string)> f); | ||||||
|   const std::vector<HomeAssistantStateSubscription> &get_state_subs() const; |   const std::vector<HomeAssistantStateSubscription> &get_state_subs() const; | ||||||
|   const std::vector<UserServiceDescriptor *> &get_user_services() const { return this->user_services_; } |   const std::vector<UserServiceDescriptor *> &get_user_services() const { | ||||||
|  | #ifdef USE_API_YAML_SERVICES | ||||||
|  |     return this->user_services_; | ||||||
|  | #else | ||||||
|  |     static const std::vector<UserServiceDescriptor *> empty; | ||||||
|  |     return this->user_services_ ? *this->user_services_ : empty; | ||||||
|  | #endif | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | #ifdef USE_API_CLIENT_CONNECTED_TRIGGER | ||||||
|   Trigger<std::string, std::string> *get_client_connected_trigger() const { return this->client_connected_trigger_; } |   Trigger<std::string, std::string> *get_client_connected_trigger() const { return this->client_connected_trigger_; } | ||||||
|  | #endif | ||||||
|  | #ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER | ||||||
|   Trigger<std::string, std::string> *get_client_disconnected_trigger() const { |   Trigger<std::string, std::string> *get_client_disconnected_trigger() const { | ||||||
|     return this->client_disconnected_trigger_; |     return this->client_disconnected_trigger_; | ||||||
|   } |   } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   void schedule_reboot_timeout_(); |   void schedule_reboot_timeout_(); | ||||||
|   // Pointers and pointer-like types first (4 bytes each) |   // Pointers and pointer-like types first (4 bytes each) | ||||||
|   std::unique_ptr<socket::Socket> socket_ = nullptr; |   std::unique_ptr<socket::Socket> socket_ = nullptr; | ||||||
|  | #ifdef USE_API_CLIENT_CONNECTED_TRIGGER | ||||||
|   Trigger<std::string, std::string> *client_connected_trigger_ = new Trigger<std::string, std::string>(); |   Trigger<std::string, std::string> *client_connected_trigger_ = new Trigger<std::string, std::string>(); | ||||||
|  | #endif | ||||||
|  | #ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER | ||||||
|   Trigger<std::string, std::string> *client_disconnected_trigger_ = new Trigger<std::string, std::string>(); |   Trigger<std::string, std::string> *client_disconnected_trigger_ = new Trigger<std::string, std::string>(); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   // 4-byte aligned types |   // 4-byte aligned types | ||||||
|   uint32_t reboot_timeout_{300000}; |   uint32_t reboot_timeout_{300000}; | ||||||
| @@ -157,7 +183,15 @@ class APIServer : public Component, public Controller { | |||||||
|   std::string password_; |   std::string password_; | ||||||
|   std::vector<uint8_t> shared_write_buffer_;  // Shared proto write buffer for all connections |   std::vector<uint8_t> shared_write_buffer_;  // Shared proto write buffer for all connections | ||||||
|   std::vector<HomeAssistantStateSubscription> state_subs_; |   std::vector<HomeAssistantStateSubscription> state_subs_; | ||||||
|  | #ifdef USE_API_YAML_SERVICES | ||||||
|  |   // When services are defined in YAML, we know at compile time that services will be registered | ||||||
|   std::vector<UserServiceDescriptor *> user_services_; |   std::vector<UserServiceDescriptor *> user_services_; | ||||||
|  | #else | ||||||
|  |   // Services can still be registered at runtime by CustomAPIDevice components even when not | ||||||
|  |   // defined in YAML. Using unique_ptr allows lazy allocation, saving 12 bytes in the common | ||||||
|  |   // case where no services (YAML or custom) are used. | ||||||
|  |   std::unique_ptr<std::vector<UserServiceDescriptor *>> user_services_; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   // Group smaller types together |   // Group smaller types together | ||||||
|   uint16_t port_{6053}; |   uint16_t port_{6053}; | ||||||
|   | |||||||
| @@ -69,8 +69,8 @@ class ESPColorCorrection { | |||||||
|  protected: |  protected: | ||||||
|   uint8_t gamma_table_[256]; |   uint8_t gamma_table_[256]; | ||||||
|   uint8_t gamma_reverse_table_[256]; |   uint8_t gamma_reverse_table_[256]; | ||||||
|   Color max_brightness_; |  | ||||||
|   uint8_t local_brightness_{255}; |   uint8_t local_brightness_{255}; | ||||||
|  |   Color max_brightness_; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace light | }  // namespace light | ||||||
|   | |||||||
| @@ -136,7 +136,7 @@ LightColorValues LightCall::validate_() { | |||||||
|  |  | ||||||
|   // Color mode check |   // Color mode check | ||||||
|   if (this->color_mode_.has_value() && !traits.supports_color_mode(this->color_mode_.value())) { |   if (this->color_mode_.has_value() && !traits.supports_color_mode(this->color_mode_.value())) { | ||||||
|     ESP_LOGW(TAG, "'%s' - This light does not support color mode %s!", name, |     ESP_LOGW(TAG, "'%s' does not support color mode %s", name, | ||||||
|              LOG_STR_ARG(color_mode_to_human(this->color_mode_.value()))); |              LOG_STR_ARG(color_mode_to_human(this->color_mode_.value()))); | ||||||
|     this->color_mode_.reset(); |     this->color_mode_.reset(); | ||||||
|   } |   } | ||||||
| @@ -152,20 +152,20 @@ LightColorValues LightCall::validate_() { | |||||||
|  |  | ||||||
|   // Brightness exists check |   // Brightness exists check | ||||||
|   if (this->brightness_.has_value() && *this->brightness_ > 0.0f && !(color_mode & ColorCapability::BRIGHTNESS)) { |   if (this->brightness_.has_value() && *this->brightness_ > 0.0f && !(color_mode & ColorCapability::BRIGHTNESS)) { | ||||||
|     ESP_LOGW(TAG, "'%s' - This light does not support setting brightness!", name); |     ESP_LOGW(TAG, "'%s': setting brightness not supported", name); | ||||||
|     this->brightness_.reset(); |     this->brightness_.reset(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Transition length possible check |   // Transition length possible check | ||||||
|   if (this->transition_length_.has_value() && *this->transition_length_ != 0 && |   if (this->transition_length_.has_value() && *this->transition_length_ != 0 && | ||||||
|       !(color_mode & ColorCapability::BRIGHTNESS)) { |       !(color_mode & ColorCapability::BRIGHTNESS)) { | ||||||
|     ESP_LOGW(TAG, "'%s' - This light does not support transitions!", name); |     ESP_LOGW(TAG, "'%s': transitions not supported", name); | ||||||
|     this->transition_length_.reset(); |     this->transition_length_.reset(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Color brightness exists check |   // Color brightness exists check | ||||||
|   if (this->color_brightness_.has_value() && *this->color_brightness_ > 0.0f && !(color_mode & ColorCapability::RGB)) { |   if (this->color_brightness_.has_value() && *this->color_brightness_ > 0.0f && !(color_mode & ColorCapability::RGB)) { | ||||||
|     ESP_LOGW(TAG, "'%s' - This color mode does not support setting RGB brightness!", name); |     ESP_LOGW(TAG, "'%s': color mode does not support setting RGB brightness", name); | ||||||
|     this->color_brightness_.reset(); |     this->color_brightness_.reset(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -173,7 +173,7 @@ LightColorValues LightCall::validate_() { | |||||||
|   if ((this->red_.has_value() && *this->red_ > 0.0f) || (this->green_.has_value() && *this->green_ > 0.0f) || |   if ((this->red_.has_value() && *this->red_ > 0.0f) || (this->green_.has_value() && *this->green_ > 0.0f) || | ||||||
|       (this->blue_.has_value() && *this->blue_ > 0.0f)) { |       (this->blue_.has_value() && *this->blue_ > 0.0f)) { | ||||||
|     if (!(color_mode & ColorCapability::RGB)) { |     if (!(color_mode & ColorCapability::RGB)) { | ||||||
|       ESP_LOGW(TAG, "'%s' - This color mode does not support setting RGB color!", name); |       ESP_LOGW(TAG, "'%s': color mode does not support setting RGB color", name); | ||||||
|       this->red_.reset(); |       this->red_.reset(); | ||||||
|       this->green_.reset(); |       this->green_.reset(); | ||||||
|       this->blue_.reset(); |       this->blue_.reset(); | ||||||
| @@ -183,14 +183,14 @@ LightColorValues LightCall::validate_() { | |||||||
|   // White value exists check |   // White value exists check | ||||||
|   if (this->white_.has_value() && *this->white_ > 0.0f && |   if (this->white_.has_value() && *this->white_ > 0.0f && | ||||||
|       !(color_mode & ColorCapability::WHITE || color_mode & ColorCapability::COLD_WARM_WHITE)) { |       !(color_mode & ColorCapability::WHITE || color_mode & ColorCapability::COLD_WARM_WHITE)) { | ||||||
|     ESP_LOGW(TAG, "'%s' - This color mode does not support setting white value!", name); |     ESP_LOGW(TAG, "'%s': color mode does not support setting white value", name); | ||||||
|     this->white_.reset(); |     this->white_.reset(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Color temperature exists check |   // Color temperature exists check | ||||||
|   if (this->color_temperature_.has_value() && |   if (this->color_temperature_.has_value() && | ||||||
|       !(color_mode & ColorCapability::COLOR_TEMPERATURE || color_mode & ColorCapability::COLD_WARM_WHITE)) { |       !(color_mode & ColorCapability::COLOR_TEMPERATURE || color_mode & ColorCapability::COLD_WARM_WHITE)) { | ||||||
|     ESP_LOGW(TAG, "'%s' - This color mode does not support setting color temperature!", name); |     ESP_LOGW(TAG, "'%s': color mode does not support setting color temperature", name); | ||||||
|     this->color_temperature_.reset(); |     this->color_temperature_.reset(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -198,7 +198,7 @@ LightColorValues LightCall::validate_() { | |||||||
|   if ((this->cold_white_.has_value() && *this->cold_white_ > 0.0f) || |   if ((this->cold_white_.has_value() && *this->cold_white_ > 0.0f) || | ||||||
|       (this->warm_white_.has_value() && *this->warm_white_ > 0.0f)) { |       (this->warm_white_.has_value() && *this->warm_white_ > 0.0f)) { | ||||||
|     if (!(color_mode & ColorCapability::COLD_WARM_WHITE)) { |     if (!(color_mode & ColorCapability::COLD_WARM_WHITE)) { | ||||||
|       ESP_LOGW(TAG, "'%s' - This color mode does not support setting cold/warm white value!", name); |       ESP_LOGW(TAG, "'%s': color mode does not support setting cold/warm white value", name); | ||||||
|       this->cold_white_.reset(); |       this->cold_white_.reset(); | ||||||
|       this->warm_white_.reset(); |       this->warm_white_.reset(); | ||||||
|     } |     } | ||||||
| @@ -208,7 +208,7 @@ LightColorValues LightCall::validate_() { | |||||||
|   if (name_##_.has_value()) { \ |   if (name_##_.has_value()) { \ | ||||||
|     auto val = *name_##_; \ |     auto val = *name_##_; \ | ||||||
|     if (val < (min) || val > (max)) { \ |     if (val < (min) || val > (max)) { \ | ||||||
|       ESP_LOGW(TAG, "'%s' - %s value %.2f is out of range [%.1f - %.1f]!", name, LOG_STR_LITERAL(upper_name), val, \ |       ESP_LOGW(TAG, "'%s': %s value %.2f is out of range [%.1f - %.1f]", name, LOG_STR_LITERAL(upper_name), val, \ | ||||||
|                (min), (max)); \ |                (min), (max)); \ | ||||||
|       name_##_ = clamp(val, (min), (max)); \ |       name_##_ = clamp(val, (min), (max)); \ | ||||||
|     } \ |     } \ | ||||||
| @@ -270,7 +270,7 @@ LightColorValues LightCall::validate_() { | |||||||
|  |  | ||||||
|   // Flash length check |   // Flash length check | ||||||
|   if (this->has_flash_() && *this->flash_length_ == 0) { |   if (this->has_flash_() && *this->flash_length_ == 0) { | ||||||
|     ESP_LOGW(TAG, "'%s' - Flash length must be greater than zero!", name); |     ESP_LOGW(TAG, "'%s': flash length must be greater than zero", name); | ||||||
|     this->flash_length_.reset(); |     this->flash_length_.reset(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -284,18 +284,18 @@ LightColorValues LightCall::validate_() { | |||||||
|  |  | ||||||
|   // validate effect index |   // validate effect index | ||||||
|   if (this->has_effect_() && *this->effect_ > this->parent_->effects_.size()) { |   if (this->has_effect_() && *this->effect_ > this->parent_->effects_.size()) { | ||||||
|     ESP_LOGW(TAG, "'%s' - Invalid effect index %" PRIu32 "!", name, *this->effect_); |     ESP_LOGW(TAG, "'%s': invalid effect index %" PRIu32, name, *this->effect_); | ||||||
|     this->effect_.reset(); |     this->effect_.reset(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (this->has_effect_() && (this->has_transition_() || this->has_flash_())) { |   if (this->has_effect_() && (this->has_transition_() || this->has_flash_())) { | ||||||
|     ESP_LOGW(TAG, "'%s' - Effect cannot be used together with transition/flash!", name); |     ESP_LOGW(TAG, "'%s': effect cannot be used with transition/flash", name); | ||||||
|     this->transition_length_.reset(); |     this->transition_length_.reset(); | ||||||
|     this->flash_length_.reset(); |     this->flash_length_.reset(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (this->has_flash_() && this->has_transition_()) { |   if (this->has_flash_() && this->has_transition_()) { | ||||||
|     ESP_LOGW(TAG, "'%s' - Flash cannot be used together with transition!", name); |     ESP_LOGW(TAG, "'%s': flash cannot be used with transition", name); | ||||||
|     this->transition_length_.reset(); |     this->transition_length_.reset(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -311,7 +311,7 @@ LightColorValues LightCall::validate_() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (this->has_transition_() && !supports_transition) { |   if (this->has_transition_() && !supports_transition) { | ||||||
|     ESP_LOGW(TAG, "'%s' - Light does not support transitions!", name); |     ESP_LOGW(TAG, "'%s': transitions not supported", name); | ||||||
|     this->transition_length_.reset(); |     this->transition_length_.reset(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -320,7 +320,7 @@ LightColorValues LightCall::validate_() { | |||||||
|   // Reason: When user turns off the light in frontend, the effect should also stop |   // Reason: When user turns off the light in frontend, the effect should also stop | ||||||
|   if (!this->has_flash_() && !this->state_.value_or(v.is_on())) { |   if (!this->has_flash_() && !this->state_.value_or(v.is_on())) { | ||||||
|     if (this->has_effect_()) { |     if (this->has_effect_()) { | ||||||
|       ESP_LOGW(TAG, "'%s' - Cannot start an effect when turning off!", name); |       ESP_LOGW(TAG, "'%s': cannot start effect when turning off", name); | ||||||
|       this->effect_.reset(); |       this->effect_.reset(); | ||||||
|     } else if (this->parent_->active_effect_index_ != 0 && explicit_turn_off_request) { |     } else if (this->parent_->active_effect_index_ != 0 && explicit_turn_off_request) { | ||||||
|       // Auto turn off effect |       // Auto turn off effect | ||||||
| @@ -348,7 +348,7 @@ void LightCall::transform_parameters_() { | |||||||
|       !(*this->color_mode_ & ColorCapability::WHITE) &&                                                // |       !(*this->color_mode_ & ColorCapability::WHITE) &&                                                // | ||||||
|       !(*this->color_mode_ & ColorCapability::COLOR_TEMPERATURE) &&                                    // |       !(*this->color_mode_ & ColorCapability::COLOR_TEMPERATURE) &&                                    // | ||||||
|       traits.get_min_mireds() > 0.0f && traits.get_max_mireds() > 0.0f) { |       traits.get_min_mireds() > 0.0f && traits.get_max_mireds() > 0.0f) { | ||||||
|     ESP_LOGD(TAG, "'%s' - Setting cold/warm white channels using white/color temperature values.", |     ESP_LOGD(TAG, "'%s': setting cold/warm white channels using white/color temperature values", | ||||||
|              this->parent_->get_name().c_str()); |              this->parent_->get_name().c_str()); | ||||||
|     if (this->color_temperature_.has_value()) { |     if (this->color_temperature_.has_value()) { | ||||||
|       const float color_temp = clamp(*this->color_temperature_, traits.get_min_mireds(), traits.get_max_mireds()); |       const float color_temp = clamp(*this->color_temperature_, traits.get_min_mireds(), traits.get_max_mireds()); | ||||||
| @@ -388,8 +388,8 @@ ColorMode LightCall::compute_color_mode_() { | |||||||
|  |  | ||||||
|   // Don't change if the current mode is suitable. |   // Don't change if the current mode is suitable. | ||||||
|   if (suitable_modes.count(current_mode) > 0) { |   if (suitable_modes.count(current_mode) > 0) { | ||||||
|     ESP_LOGI(TAG, "'%s' - Keeping current color mode %s for call without color mode.", |     ESP_LOGI(TAG, "'%s': color mode not specified; retaining %s", this->parent_->get_name().c_str(), | ||||||
|              this->parent_->get_name().c_str(), LOG_STR_ARG(color_mode_to_human(current_mode))); |              LOG_STR_ARG(color_mode_to_human(current_mode))); | ||||||
|     return current_mode; |     return current_mode; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -398,7 +398,7 @@ ColorMode LightCall::compute_color_mode_() { | |||||||
|     if (supported_modes.count(mode) == 0) |     if (supported_modes.count(mode) == 0) | ||||||
|       continue; |       continue; | ||||||
|  |  | ||||||
|     ESP_LOGI(TAG, "'%s' - Using color mode %s for call without color mode.", this->parent_->get_name().c_str(), |     ESP_LOGI(TAG, "'%s': color mode not specified; using %s", this->parent_->get_name().c_str(), | ||||||
|              LOG_STR_ARG(color_mode_to_human(mode))); |              LOG_STR_ARG(color_mode_to_human(mode))); | ||||||
|     return mode; |     return mode; | ||||||
|   } |   } | ||||||
| @@ -406,8 +406,8 @@ ColorMode LightCall::compute_color_mode_() { | |||||||
|   // There's no supported mode for this call, so warn, use the current more or a mode at random and let validation strip |   // There's no supported mode for this call, so warn, use the current more or a mode at random and let validation strip | ||||||
|   // out whatever we don't support. |   // out whatever we don't support. | ||||||
|   auto color_mode = current_mode != ColorMode::UNKNOWN ? current_mode : *supported_modes.begin(); |   auto color_mode = current_mode != ColorMode::UNKNOWN ? current_mode : *supported_modes.begin(); | ||||||
|   ESP_LOGW(TAG, "'%s' - No color mode suitable for this call supported, defaulting to %s!", |   ESP_LOGW(TAG, "'%s': no suitable color mode supported; defaulting to %s", this->parent_->get_name().c_str(), | ||||||
|            this->parent_->get_name().c_str(), LOG_STR_ARG(color_mode_to_human(color_mode))); |            LOG_STR_ARG(color_mode_to_human(color_mode))); | ||||||
|   return color_mode; |   return color_mode; | ||||||
| } | } | ||||||
| std::set<ColorMode> LightCall::get_suitable_color_modes_() { | std::set<ColorMode> LightCall::get_suitable_color_modes_() { | ||||||
| @@ -472,7 +472,7 @@ LightCall &LightCall::set_effect(const std::string &effect) { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (!found) { |   if (!found) { | ||||||
|     ESP_LOGW(TAG, "'%s' - No such effect '%s'", this->parent_->get_name().c_str(), effect.c_str()); |     ESP_LOGW(TAG, "'%s': no such effect '%s'", this->parent_->get_name().c_str(), effect.c_str()); | ||||||
|   } |   } | ||||||
|   return *this; |   return *this; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -225,6 +225,11 @@ class LightState : public EntityBase, public Component { | |||||||
|   /// Gamma correction factor for the light. |   /// Gamma correction factor for the light. | ||||||
|   float gamma_correct_{}; |   float gamma_correct_{}; | ||||||
|  |  | ||||||
|  |   /// Whether the light value should be written in the next cycle. | ||||||
|  |   bool next_write_{true}; | ||||||
|  |   // for effects, true if a transformer (transition) is active. | ||||||
|  |   bool is_transformer_active_ = false; | ||||||
|  |  | ||||||
|   /// Object used to store the persisted values of the light. |   /// Object used to store the persisted values of the light. | ||||||
|   ESPPreferenceObject rtc_; |   ESPPreferenceObject rtc_; | ||||||
|  |  | ||||||
| @@ -247,10 +252,6 @@ class LightState : public EntityBase, public Component { | |||||||
|  |  | ||||||
|   /// Restore mode of the light. |   /// Restore mode of the light. | ||||||
|   LightRestoreMode restore_mode_; |   LightRestoreMode restore_mode_; | ||||||
|   /// Whether the light value should be written in the next cycle. |  | ||||||
|   bool next_write_{true}; |  | ||||||
|   // for effects, true if a transformer (transition) is active. |  | ||||||
|   bool is_transformer_active_ = false; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace light | }  // namespace light | ||||||
|   | |||||||
| @@ -997,7 +997,7 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) { | |||||||
|   auto config = this->preset_config_.find(preset); |   auto config = this->preset_config_.find(preset); | ||||||
|  |  | ||||||
|   if (config != this->preset_config_.end()) { |   if (config != this->preset_config_.end()) { | ||||||
|     ESP_LOGI(TAG, "Preset %s requested", LOG_STR_ARG(climate::climate_preset_to_string(preset))); |     ESP_LOGV(TAG, "Preset %s requested", LOG_STR_ARG(climate::climate_preset_to_string(preset))); | ||||||
|     if (this->change_preset_internal_(config->second) || (!this->preset.has_value()) || |     if (this->change_preset_internal_(config->second) || (!this->preset.has_value()) || | ||||||
|         this->preset.value() != preset) { |         this->preset.value() != preset) { | ||||||
|       // Fire any preset changed trigger if defined |       // Fire any preset changed trigger if defined | ||||||
| @@ -1015,7 +1015,7 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) { | |||||||
|     this->custom_preset.reset(); |     this->custom_preset.reset(); | ||||||
|     this->preset = preset; |     this->preset = preset; | ||||||
|   } else { |   } else { | ||||||
|     ESP_LOGE(TAG, "Preset %s is not configured, ignoring.", LOG_STR_ARG(climate::climate_preset_to_string(preset))); |     ESP_LOGW(TAG, "Preset %s not configured; ignoring", LOG_STR_ARG(climate::climate_preset_to_string(preset))); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1023,7 +1023,7 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset) | |||||||
|   auto config = this->custom_preset_config_.find(custom_preset); |   auto config = this->custom_preset_config_.find(custom_preset); | ||||||
|  |  | ||||||
|   if (config != this->custom_preset_config_.end()) { |   if (config != this->custom_preset_config_.end()) { | ||||||
|     ESP_LOGI(TAG, "Custom preset %s requested", custom_preset.c_str()); |     ESP_LOGV(TAG, "Custom preset %s requested", custom_preset.c_str()); | ||||||
|     if (this->change_preset_internal_(config->second) || (!this->custom_preset.has_value()) || |     if (this->change_preset_internal_(config->second) || (!this->custom_preset.has_value()) || | ||||||
|         this->custom_preset.value() != custom_preset) { |         this->custom_preset.value() != custom_preset) { | ||||||
|       // Fire any preset changed trigger if defined |       // Fire any preset changed trigger if defined | ||||||
| @@ -1041,7 +1041,7 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset) | |||||||
|     this->preset.reset(); |     this->preset.reset(); | ||||||
|     this->custom_preset = custom_preset; |     this->custom_preset = custom_preset; | ||||||
|   } else { |   } else { | ||||||
|     ESP_LOGE(TAG, "Custom Preset %s is not configured, ignoring.", custom_preset.c_str()); |     ESP_LOGW(TAG, "Custom preset %s not configured; ignoring", custom_preset.c_str()); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1298,7 +1298,7 @@ void ThermostatClimate::dump_config() { | |||||||
|   if (this->supports_two_points_) { |   if (this->supports_two_points_) { | ||||||
|     ESP_LOGCONFIG(TAG, "  Minimum Set Point Differential: %.1f°C", this->set_point_minimum_differential_); |     ESP_LOGCONFIG(TAG, "  Minimum Set Point Differential: %.1f°C", this->set_point_minimum_differential_); | ||||||
|   } |   } | ||||||
|   ESP_LOGCONFIG(TAG, "  Start-up Delay Enabled: %s", YESNO(this->use_startup_delay_)); |   ESP_LOGCONFIG(TAG, "  Use Start-up Delay: %s", YESNO(this->use_startup_delay_)); | ||||||
|   if (this->supports_cool_) { |   if (this->supports_cool_) { | ||||||
|     ESP_LOGCONFIG(TAG, |     ESP_LOGCONFIG(TAG, | ||||||
|                   "  Cooling Parameters:\n" |                   "  Cooling Parameters:\n" | ||||||
| @@ -1353,44 +1353,47 @@ void ThermostatClimate::dump_config() { | |||||||
|   } |   } | ||||||
|   ESP_LOGCONFIG(TAG, "  Minimum Idle Time: %" PRIu32 "s", this->timer_[thermostat::TIMER_IDLE_ON].time / 1000); |   ESP_LOGCONFIG(TAG, "  Minimum Idle Time: %" PRIu32 "s", this->timer_[thermostat::TIMER_IDLE_ON].time / 1000); | ||||||
|   ESP_LOGCONFIG(TAG, |   ESP_LOGCONFIG(TAG, | ||||||
|                 "  Supports AUTO: %s\n" |                 "  Supported MODES:\n" | ||||||
|                 "  Supports HEAT/COOL: %s\n" |                 "    AUTO: %s\n" | ||||||
|                 "  Supports COOL: %s\n" |                 "    HEAT/COOL: %s\n" | ||||||
|                 "  Supports DRY: %s\n" |                 "    HEAT: %s\n" | ||||||
|                 "  Supports FAN_ONLY: %s\n" |                 "    COOL: %s\n" | ||||||
|                 "  Supports FAN_ONLY_ACTION_USES_FAN_MODE_TIMER: %s\n" |                 "    DRY: %s\n" | ||||||
|                 "  Supports FAN_ONLY_COOLING: %s", |                 "    FAN_ONLY: %s\n" | ||||||
|                 YESNO(this->supports_auto_), YESNO(this->supports_heat_cool_), YESNO(this->supports_cool_), |                 "    FAN_ONLY_ACTION_USES_FAN_MODE_TIMER: %s\n" | ||||||
|                 YESNO(this->supports_dry_), YESNO(this->supports_fan_only_), |                 "    FAN_ONLY_COOLING: %s", | ||||||
|  |                 YESNO(this->supports_auto_), YESNO(this->supports_heat_cool_), YESNO(this->supports_heat_), | ||||||
|  |                 YESNO(this->supports_cool_), YESNO(this->supports_dry_), YESNO(this->supports_fan_only_), | ||||||
|                 YESNO(this->supports_fan_only_action_uses_fan_mode_timer_), YESNO(this->supports_fan_only_cooling_)); |                 YESNO(this->supports_fan_only_action_uses_fan_mode_timer_), YESNO(this->supports_fan_only_cooling_)); | ||||||
|   if (this->supports_cool_) { |   if (this->supports_cool_) { | ||||||
|     ESP_LOGCONFIG(TAG, "  Supports FAN_WITH_COOLING: %s", YESNO(this->supports_fan_with_cooling_)); |     ESP_LOGCONFIG(TAG, "    FAN_WITH_COOLING: %s", YESNO(this->supports_fan_with_cooling_)); | ||||||
|   } |   } | ||||||
|   if (this->supports_heat_) { |   if (this->supports_heat_) { | ||||||
|     ESP_LOGCONFIG(TAG, "  Supports FAN_WITH_HEATING: %s", YESNO(this->supports_fan_with_heating_)); |     ESP_LOGCONFIG(TAG, "    FAN_WITH_HEATING: %s", YESNO(this->supports_fan_with_heating_)); | ||||||
|   } |   } | ||||||
|   ESP_LOGCONFIG(TAG, "  Supports HEAT: %s", YESNO(this->supports_heat_)); |  | ||||||
|   ESP_LOGCONFIG(TAG, |   ESP_LOGCONFIG(TAG, | ||||||
|                 "  Supports FAN MODE ON: %s\n" |                 "  Supported FAN MODES:\n" | ||||||
|                 "  Supports FAN MODE OFF: %s\n" |                 "    ON: %s\n" | ||||||
|                 "  Supports FAN MODE AUTO: %s\n" |                 "    OFF: %s\n" | ||||||
|                 "  Supports FAN MODE LOW: %s\n" |                 "    AUTO: %s\n" | ||||||
|                 "  Supports FAN MODE MEDIUM: %s\n" |                 "    LOW: %s\n" | ||||||
|                 "  Supports FAN MODE HIGH: %s\n" |                 "    MEDIUM: %s\n" | ||||||
|                 "  Supports FAN MODE MIDDLE: %s\n" |                 "    HIGH: %s\n" | ||||||
|                 "  Supports FAN MODE FOCUS: %s\n" |                 "    MIDDLE: %s\n" | ||||||
|                 "  Supports FAN MODE DIFFUSE: %s\n" |                 "    FOCUS: %s\n" | ||||||
|                 "  Supports FAN MODE QUIET: %s", |                 "    DIFFUSE: %s\n" | ||||||
|  |                 "    QUIET: %s", | ||||||
|                 YESNO(this->supports_fan_mode_on_), YESNO(this->supports_fan_mode_off_), |                 YESNO(this->supports_fan_mode_on_), YESNO(this->supports_fan_mode_off_), | ||||||
|                 YESNO(this->supports_fan_mode_auto_), YESNO(this->supports_fan_mode_low_), |                 YESNO(this->supports_fan_mode_auto_), YESNO(this->supports_fan_mode_low_), | ||||||
|                 YESNO(this->supports_fan_mode_medium_), YESNO(this->supports_fan_mode_high_), |                 YESNO(this->supports_fan_mode_medium_), YESNO(this->supports_fan_mode_high_), | ||||||
|                 YESNO(this->supports_fan_mode_middle_), YESNO(this->supports_fan_mode_focus_), |                 YESNO(this->supports_fan_mode_middle_), YESNO(this->supports_fan_mode_focus_), | ||||||
|                 YESNO(this->supports_fan_mode_diffuse_), YESNO(this->supports_fan_mode_quiet_)); |                 YESNO(this->supports_fan_mode_diffuse_), YESNO(this->supports_fan_mode_quiet_)); | ||||||
|   ESP_LOGCONFIG(TAG, |   ESP_LOGCONFIG(TAG, | ||||||
|                 "  Supports SWING MODE BOTH: %s\n" |                 "  Supported SWING MODES:\n" | ||||||
|                 "  Supports SWING MODE OFF: %s\n" |                 "    BOTH: %s\n" | ||||||
|                 "  Supports SWING MODE HORIZONTAL: %s\n" |                 "    OFF: %s\n" | ||||||
|                 "  Supports SWING MODE VERTICAL: %s\n" |                 "    HORIZONTAL: %s\n" | ||||||
|  |                 "    VERTICAL: %s\n" | ||||||
|                 "  Supports TWO SET POINTS: %s", |                 "  Supports TWO SET POINTS: %s", | ||||||
|                 YESNO(this->supports_swing_mode_both_), YESNO(this->supports_swing_mode_off_), |                 YESNO(this->supports_swing_mode_both_), YESNO(this->supports_swing_mode_off_), | ||||||
|                 YESNO(this->supports_swing_mode_horizontal_), YESNO(this->supports_swing_mode_vertical_), |                 YESNO(this->supports_swing_mode_horizontal_), YESNO(this->supports_swing_mode_vertical_), | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ | |||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace thermostat { | namespace thermostat { | ||||||
|  |  | ||||||
| enum ThermostatClimateTimerIndex : size_t { | enum ThermostatClimateTimerIndex : uint8_t { | ||||||
|   TIMER_COOLING_MAX_RUN_TIME = 0, |   TIMER_COOLING_MAX_RUN_TIME = 0, | ||||||
|   TIMER_COOLING_OFF = 1, |   TIMER_COOLING_OFF = 1, | ||||||
|   TIMER_COOLING_ON = 2, |   TIMER_COOLING_ON = 2, | ||||||
| @@ -26,7 +26,11 @@ enum ThermostatClimateTimerIndex : size_t { | |||||||
|   TIMER_IDLE_ON = 9, |   TIMER_IDLE_ON = 9, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| enum OnBootRestoreFrom : size_t { MEMORY = 0, DEFAULT_PRESET = 1 }; | enum OnBootRestoreFrom : uint8_t { | ||||||
|  |   MEMORY = 0, | ||||||
|  |   DEFAULT_PRESET = 1, | ||||||
|  | }; | ||||||
|  |  | ||||||
| struct ThermostatClimateTimer { | struct ThermostatClimateTimer { | ||||||
|   bool active; |   bool active; | ||||||
|   uint32_t time; |   uint32_t time; | ||||||
| @@ -65,7 +69,7 @@ class ThermostatClimate : public climate::Climate, public Component { | |||||||
|  |  | ||||||
|   void set_default_preset(const std::string &custom_preset); |   void set_default_preset(const std::string &custom_preset); | ||||||
|   void set_default_preset(climate::ClimatePreset preset); |   void set_default_preset(climate::ClimatePreset preset); | ||||||
|   void set_on_boot_restore_from(thermostat::OnBootRestoreFrom on_boot_restore_from); |   void set_on_boot_restore_from(OnBootRestoreFrom on_boot_restore_from); | ||||||
|   void set_set_point_minimum_differential(float differential); |   void set_set_point_minimum_differential(float differential); | ||||||
|   void set_cool_deadband(float deadband); |   void set_cool_deadband(float deadband); | ||||||
|   void set_cool_overrun(float overrun); |   void set_cool_overrun(float overrun); | ||||||
| @@ -240,10 +244,8 @@ class ThermostatClimate : public climate::Climate, public Component { | |||||||
|   void dump_preset_config_(const char *preset_name, const ThermostatClimateTargetTempConfig &config, |   void dump_preset_config_(const char *preset_name, const ThermostatClimateTargetTempConfig &config, | ||||||
|                            bool is_default_preset); |                            bool is_default_preset); | ||||||
|  |  | ||||||
|   /// The sensor used for getting the current temperature |   /// Minimum allowable duration in seconds for action timers | ||||||
|   sensor::Sensor *sensor_{nullptr}; |   const uint8_t min_timer_duration_{1}; | ||||||
|   /// The sensor used for getting the current humidity |  | ||||||
|   sensor::Sensor *humidity_sensor_{nullptr}; |  | ||||||
|  |  | ||||||
|   /// Whether the controller supports auto/cooling/drying/fanning/heating. |   /// Whether the controller supports auto/cooling/drying/fanning/heating. | ||||||
|   /// |   /// | ||||||
| @@ -310,6 +312,31 @@ class ThermostatClimate : public climate::Climate, public Component { | |||||||
|   /// setup_complete_ blocks modifying/resetting the temps immediately after boot |   /// setup_complete_ blocks modifying/resetting the temps immediately after boot | ||||||
|   bool setup_complete_{false}; |   bool setup_complete_{false}; | ||||||
|  |  | ||||||
|  |   /// Store previously-known temperatures | ||||||
|  |   /// | ||||||
|  |   /// These are used to determine when the temperature change trigger/action needs to be called | ||||||
|  |   float prev_target_temperature_{NAN}; | ||||||
|  |   float prev_target_temperature_low_{NAN}; | ||||||
|  |   float prev_target_temperature_high_{NAN}; | ||||||
|  |  | ||||||
|  |   /// Minimum differential required between set points | ||||||
|  |   float set_point_minimum_differential_{0}; | ||||||
|  |  | ||||||
|  |   /// Hysteresis values used for computing climate actions | ||||||
|  |   float cooling_deadband_{0}; | ||||||
|  |   float cooling_overrun_{0}; | ||||||
|  |   float heating_deadband_{0}; | ||||||
|  |   float heating_overrun_{0}; | ||||||
|  |  | ||||||
|  |   /// Maximum allowable temperature deltas before engaging supplemental cooling/heating actions | ||||||
|  |   float supplemental_cool_delta_{0}; | ||||||
|  |   float supplemental_heat_delta_{0}; | ||||||
|  |  | ||||||
|  |   /// The sensor used for getting the current temperature | ||||||
|  |   sensor::Sensor *sensor_{nullptr}; | ||||||
|  |   /// The sensor used for getting the current humidity | ||||||
|  |   sensor::Sensor *humidity_sensor_{nullptr}; | ||||||
|  |  | ||||||
|   /// The trigger to call when the controller should switch to cooling action/mode. |   /// The trigger to call when the controller should switch to cooling action/mode. | ||||||
|   /// |   /// | ||||||
|   /// A null value for this attribute means that the controller has no cooling action |   /// A null value for this attribute means that the controller has no cooling action | ||||||
| @@ -399,7 +426,7 @@ class ThermostatClimate : public climate::Climate, public Component { | |||||||
|   /// The trigger to call when the target temperature(s) change(es). |   /// The trigger to call when the target temperature(s) change(es). | ||||||
|   Trigger<> *temperature_change_trigger_{nullptr}; |   Trigger<> *temperature_change_trigger_{nullptr}; | ||||||
|  |  | ||||||
|   /// The triggr to call when the preset mode changes |   /// The trigger to call when the preset mode changes | ||||||
|   Trigger<> *preset_change_trigger_{nullptr}; |   Trigger<> *preset_change_trigger_{nullptr}; | ||||||
|  |  | ||||||
|   /// A reference to the trigger that was previously active. |   /// A reference to the trigger that was previously active. | ||||||
| @@ -411,6 +438,10 @@ class ThermostatClimate : public climate::Climate, public Component { | |||||||
|   Trigger<> *prev_mode_trigger_{nullptr}; |   Trigger<> *prev_mode_trigger_{nullptr}; | ||||||
|   Trigger<> *prev_swing_mode_trigger_{nullptr}; |   Trigger<> *prev_swing_mode_trigger_{nullptr}; | ||||||
|  |  | ||||||
|  |   /// If set to DEFAULT_PRESET then the default preset is always used. When MEMORY prior | ||||||
|  |   /// state will attempt to be restored if possible | ||||||
|  |   OnBootRestoreFrom on_boot_restore_from_{OnBootRestoreFrom::MEMORY}; | ||||||
|  |  | ||||||
|   /// Store previously-known states |   /// Store previously-known states | ||||||
|   /// |   /// | ||||||
|   /// These are used to determine when a trigger/action needs to be called |   /// These are used to determine when a trigger/action needs to be called | ||||||
| @@ -419,28 +450,10 @@ class ThermostatClimate : public climate::Climate, public Component { | |||||||
|   climate::ClimateMode prev_mode_{climate::CLIMATE_MODE_OFF}; |   climate::ClimateMode prev_mode_{climate::CLIMATE_MODE_OFF}; | ||||||
|   climate::ClimateSwingMode prev_swing_mode_{climate::CLIMATE_SWING_OFF}; |   climate::ClimateSwingMode prev_swing_mode_{climate::CLIMATE_SWING_OFF}; | ||||||
|  |  | ||||||
|   /// Store previously-known temperatures |   /// Default standard preset to use on start up | ||||||
|   /// |   climate::ClimatePreset default_preset_{}; | ||||||
|   /// These are used to determine when the temperature change trigger/action needs to be called |   /// Default custom preset to use on start up | ||||||
|   float prev_target_temperature_{NAN}; |   std::string default_custom_preset_{}; | ||||||
|   float prev_target_temperature_low_{NAN}; |  | ||||||
|   float prev_target_temperature_high_{NAN}; |  | ||||||
|  |  | ||||||
|   /// Minimum differential required between set points |  | ||||||
|   float set_point_minimum_differential_{0}; |  | ||||||
|  |  | ||||||
|   /// Hysteresis values used for computing climate actions |  | ||||||
|   float cooling_deadband_{0}; |  | ||||||
|   float cooling_overrun_{0}; |  | ||||||
|   float heating_deadband_{0}; |  | ||||||
|   float heating_overrun_{0}; |  | ||||||
|  |  | ||||||
|   /// Maximum allowable temperature deltas before engauging supplemental cooling/heating actions |  | ||||||
|   float supplemental_cool_delta_{0}; |  | ||||||
|   float supplemental_heat_delta_{0}; |  | ||||||
|  |  | ||||||
|   /// Minimum allowable duration in seconds for action timers |  | ||||||
|   const uint8_t min_timer_duration_{1}; |  | ||||||
|  |  | ||||||
|   /// Climate action timers |   /// Climate action timers | ||||||
|   std::vector<ThermostatClimateTimer> timer_{ |   std::vector<ThermostatClimateTimer> timer_{ | ||||||
| @@ -460,15 +473,6 @@ class ThermostatClimate : public climate::Climate, public Component { | |||||||
|   std::map<climate::ClimatePreset, ThermostatClimateTargetTempConfig> preset_config_{}; |   std::map<climate::ClimatePreset, ThermostatClimateTargetTempConfig> preset_config_{}; | ||||||
|   /// The set of custom preset configurations this thermostat supports (eg. "My Custom Preset") |   /// The set of custom preset configurations this thermostat supports (eg. "My Custom Preset") | ||||||
|   std::map<std::string, ThermostatClimateTargetTempConfig> custom_preset_config_{}; |   std::map<std::string, ThermostatClimateTargetTempConfig> custom_preset_config_{}; | ||||||
|  |  | ||||||
|   /// Default standard preset to use on start up |  | ||||||
|   climate::ClimatePreset default_preset_{}; |  | ||||||
|   /// Default custom preset to use on start up |  | ||||||
|   std::string default_custom_preset_{}; |  | ||||||
|  |  | ||||||
|   /// If set to DEFAULT_PRESET then the default preset is always used. When MEMORY prior |  | ||||||
|   /// state will attempt to be restored if possible |  | ||||||
|   thermostat::OnBootRestoreFrom on_boot_restore_from_{thermostat::OnBootRestoreFrom::MEMORY}; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace thermostat | }  // namespace thermostat | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user