mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Merge branch 'fan_fixed' into integration
This commit is contained in:
		| @@ -425,7 +425,7 @@ message ListEntitiesFanResponse { | ||||
|   bool disabled_by_default = 9; | ||||
|   string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON"]; | ||||
|   EntityCategory entity_category = 11; | ||||
|   repeated string supported_preset_modes = 12 [(container_pointer) = "std::vector"]; | ||||
|   repeated string supported_preset_modes = 12 [(container_pointer_no_template) = "std::vector<const char *>"]; | ||||
|   uint32 device_id = 13 [(field_ifdef) = "USE_DEVICES"]; | ||||
| } | ||||
| // Deprecated in API version 1.6 - only used in deprecated fields | ||||
|   | ||||
| @@ -423,7 +423,7 @@ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *con | ||||
|   msg.supports_speed = traits.supports_speed(); | ||||
|   msg.supports_direction = traits.supports_direction(); | ||||
|   msg.supported_speed_count = traits.supported_speed_count(); | ||||
|   msg.supported_preset_modes = &traits.supported_preset_modes_for_api_(); | ||||
|   msg.supported_preset_modes = &traits.supported_preset_modes(); | ||||
|   return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size, is_single); | ||||
| } | ||||
| void APIConnection::fan_command(const FanCommandRequest &msg) { | ||||
|   | ||||
| @@ -355,8 +355,8 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const { | ||||
|   buffer.encode_string(10, this->icon_ref_); | ||||
| #endif | ||||
|   buffer.encode_uint32(11, static_cast<uint32_t>(this->entity_category)); | ||||
|   for (const auto &it : *this->supported_preset_modes) { | ||||
|     buffer.encode_string(12, it, true); | ||||
|   for (const char *it : *this->supported_preset_modes) { | ||||
|     buffer.encode_string(12, it, strlen(it), true); | ||||
|   } | ||||
| #ifdef USE_DEVICES | ||||
|   buffer.encode_uint32(13, this->device_id); | ||||
| @@ -376,8 +376,8 @@ void ListEntitiesFanResponse::calculate_size(ProtoSize &size) const { | ||||
| #endif | ||||
|   size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); | ||||
|   if (!this->supported_preset_modes->empty()) { | ||||
|     for (const auto &it : *this->supported_preset_modes) { | ||||
|       size.add_length_force(1, it.size()); | ||||
|     for (const char *it : *this->supported_preset_modes) { | ||||
|       size.add_length_force(1, strlen(it)); | ||||
|     } | ||||
|   } | ||||
| #ifdef USE_DEVICES | ||||
|   | ||||
| @@ -725,7 +725,7 @@ class ListEntitiesFanResponse final : public InfoResponseProtoMessage { | ||||
|   bool supports_speed{false}; | ||||
|   bool supports_direction{false}; | ||||
|   int32_t supported_speed_count{0}; | ||||
|   const std::vector<std::string> *supported_preset_modes{}; | ||||
|   const std::vector<const char *> *supported_preset_modes{}; | ||||
|   void encode(ProtoWriteBuffer buffer) const override; | ||||
|   void calculate_size(ProtoSize &size) const override; | ||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | ||||
|   | ||||
| @@ -53,7 +53,7 @@ void FanCall::validate_() { | ||||
|     const auto &preset_modes = traits.supported_preset_modes(); | ||||
|     bool found = false; | ||||
|     for (const auto &mode : preset_modes) { | ||||
|       if (mode == this->preset_mode_) { | ||||
|       if (strcmp(mode, this->preset_mode_.c_str()) == 0) { | ||||
|         found = true; | ||||
|         break; | ||||
|       } | ||||
| @@ -99,11 +99,12 @@ FanCall FanRestoreState::to_call(Fan &fan) { | ||||
|   call.set_speed(this->speed); | ||||
|   call.set_direction(this->direction); | ||||
|  | ||||
|   if (fan.get_traits().supports_preset_modes()) { | ||||
|   auto traits = fan.get_traits(); | ||||
|   if (traits.supports_preset_modes()) { | ||||
|     // Use stored preset index to get preset name | ||||
|     const auto &preset_modes = fan.get_traits().supported_preset_modes(); | ||||
|     const auto &preset_modes = traits.supported_preset_modes(); | ||||
|     if (this->preset_mode < preset_modes.size()) { | ||||
|       call.set_preset_mode(*std::next(preset_modes.begin(), this->preset_mode)); | ||||
|       call.set_preset_mode(preset_modes[this->preset_mode]); | ||||
|     } | ||||
|   } | ||||
|   return call; | ||||
| @@ -114,11 +115,12 @@ void FanRestoreState::apply(Fan &fan) { | ||||
|   fan.speed = this->speed; | ||||
|   fan.direction = this->direction; | ||||
|  | ||||
|   if (fan.get_traits().supports_preset_modes()) { | ||||
|   auto traits = fan.get_traits(); | ||||
|   if (traits.supports_preset_modes()) { | ||||
|     // Use stored preset index to get preset name | ||||
|     const auto &preset_modes = fan.get_traits().supported_preset_modes(); | ||||
|     const auto &preset_modes = traits.supported_preset_modes(); | ||||
|     if (this->preset_mode < preset_modes.size()) { | ||||
|       fan.preset_mode = *std::next(preset_modes.begin(), this->preset_mode); | ||||
|       fan.preset_mode = preset_modes[this->preset_mode]; | ||||
|     } | ||||
|   } | ||||
|   fan.publish_state(); | ||||
| @@ -189,18 +191,20 @@ void Fan::save_state_() { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   auto traits = this->get_traits(); | ||||
|  | ||||
|   FanRestoreState state{}; | ||||
|   state.state = this->state; | ||||
|   state.oscillating = this->oscillating; | ||||
|   state.speed = this->speed; | ||||
|   state.direction = this->direction; | ||||
|  | ||||
|   if (this->get_traits().supports_preset_modes() && !this->preset_mode.empty()) { | ||||
|     const auto &preset_modes = this->get_traits().supported_preset_modes(); | ||||
|   if (traits.supports_preset_modes() && !this->preset_mode.empty()) { | ||||
|     const auto &preset_modes = traits.supported_preset_modes(); | ||||
|     // Store index of current preset mode | ||||
|     size_t i = 0; | ||||
|     for (const auto &mode : preset_modes) { | ||||
|       if (mode == this->preset_mode) { | ||||
|       if (strcmp(mode, this->preset_mode.c_str()) == 0) { | ||||
|         state.preset_mode = i; | ||||
|         break; | ||||
|       } | ||||
| @@ -228,8 +232,8 @@ void Fan::dump_traits_(const char *tag, const char *prefix) { | ||||
|   } | ||||
|   if (traits.supports_preset_modes()) { | ||||
|     ESP_LOGCONFIG(tag, "%s  Supported presets:", prefix); | ||||
|     for (const std::string &s : traits.supported_preset_modes()) | ||||
|       ESP_LOGCONFIG(tag, "%s    - %s", prefix, s.c_str()); | ||||
|     for (const char *s : traits.supported_preset_modes()) | ||||
|       ESP_LOGCONFIG(tag, "%s    - %s", prefix, s); | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,15 +1,10 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <vector> | ||||
| #include <initializer_list> | ||||
|  | ||||
| namespace esphome { | ||||
|  | ||||
| #ifdef USE_API | ||||
| namespace api { | ||||
| class APIConnection; | ||||
| }  // namespace api | ||||
| #endif | ||||
|  | ||||
| namespace fan { | ||||
|  | ||||
| class FanTraits { | ||||
| @@ -35,27 +30,22 @@ class FanTraits { | ||||
|   /// Set whether this fan supports changing direction | ||||
|   void set_direction(bool direction) { this->direction_ = direction; } | ||||
|   /// Return the preset modes supported by the fan. | ||||
|   const std::vector<std::string> &supported_preset_modes() const { return this->preset_modes_; } | ||||
|   /// Set the preset modes supported by the fan. | ||||
|   void set_supported_preset_modes(const std::vector<std::string> &preset_modes) { this->preset_modes_ = preset_modes; } | ||||
|   const std::vector<const char *> &supported_preset_modes() const { return this->preset_modes_; } | ||||
|   /// Set the preset modes supported by the fan (from initializer list). | ||||
|   void set_supported_preset_modes(std::initializer_list<const char *> preset_modes) { | ||||
|     this->preset_modes_ = preset_modes; | ||||
|   } | ||||
|   /// Set the preset modes supported by the fan (from vector). | ||||
|   void set_supported_preset_modes(const std::vector<const char *> &preset_modes) { this->preset_modes_ = preset_modes; } | ||||
|   /// Return if preset modes are supported | ||||
|   bool supports_preset_modes() const { return !this->preset_modes_.empty(); } | ||||
|  | ||||
|  protected: | ||||
| #ifdef USE_API | ||||
|   // The API connection is a friend class to access internal methods | ||||
|   friend class api::APIConnection; | ||||
|   // This method returns a reference to the internal preset modes. | ||||
|   // It is used by the API to avoid copying data when encoding messages. | ||||
|   // Warning: Do not use this method outside of the API connection code. | ||||
|   // It returns a reference to internal data that can be invalidated. | ||||
|   const std::vector<std::string> &supported_preset_modes_for_api_() const { return this->preset_modes_; } | ||||
| #endif | ||||
|   bool oscillation_{false}; | ||||
|   bool speed_{false}; | ||||
|   bool direction_{false}; | ||||
|   int speed_count_{}; | ||||
|   std::vector<std::string> preset_modes_{}; | ||||
|   std::vector<const char *> preset_modes_{}; | ||||
| }; | ||||
|  | ||||
| }  // namespace fan | ||||
|   | ||||
| @@ -1,7 +1,5 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <set> | ||||
|  | ||||
| #include "esphome/core/automation.h" | ||||
| #include "esphome/components/output/binary_output.h" | ||||
| #include "esphome/components/output/float_output.h" | ||||
| @@ -22,7 +20,7 @@ class HBridgeFan : public Component, public fan::Fan { | ||||
|   void set_pin_a(output::FloatOutput *pin_a) { pin_a_ = pin_a; } | ||||
|   void set_pin_b(output::FloatOutput *pin_b) { pin_b_ = pin_b; } | ||||
|   void set_enable_pin(output::FloatOutput *enable) { enable_ = enable; } | ||||
|   void set_preset_modes(const std::vector<std::string> &presets) { preset_modes_ = presets; } | ||||
|   void set_preset_modes(std::initializer_list<const char *> presets) { preset_modes_ = presets; } | ||||
|  | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
| @@ -38,7 +36,7 @@ class HBridgeFan : public Component, public fan::Fan { | ||||
|   int speed_count_{}; | ||||
|   DecayMode decay_mode_{DECAY_MODE_SLOW}; | ||||
|   fan::FanTraits traits_; | ||||
|   std::vector<std::string> preset_modes_{}; | ||||
|   std::vector<const char *> preset_modes_{}; | ||||
|  | ||||
|   void control(const fan::FanCall &call) override; | ||||
|   void write_state_(); | ||||
|   | ||||
| @@ -1,7 +1,5 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <set> | ||||
|  | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/components/output/binary_output.h" | ||||
| #include "esphome/components/output/float_output.h" | ||||
| @@ -18,7 +16,7 @@ class SpeedFan : public Component, public fan::Fan { | ||||
|   void set_output(output::FloatOutput *output) { this->output_ = output; } | ||||
|   void set_oscillating(output::BinaryOutput *oscillating) { this->oscillating_ = oscillating; } | ||||
|   void set_direction(output::BinaryOutput *direction) { this->direction_ = direction; } | ||||
|   void set_preset_modes(const std::vector<std::string> &presets) { this->preset_modes_ = presets; } | ||||
|   void set_preset_modes(std::initializer_list<const char *> presets) { this->preset_modes_ = presets; } | ||||
|   fan::FanTraits get_traits() override { return this->traits_; } | ||||
|  | ||||
|  protected: | ||||
| @@ -30,7 +28,7 @@ class SpeedFan : public Component, public fan::Fan { | ||||
|   output::BinaryOutput *direction_{nullptr}; | ||||
|   int speed_count_{}; | ||||
|   fan::FanTraits traits_; | ||||
|   std::vector<std::string> preset_modes_{}; | ||||
|   std::vector<const char *> preset_modes_{}; | ||||
| }; | ||||
|  | ||||
| }  // namespace speed | ||||
|   | ||||
| @@ -1,7 +1,5 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/components/fan/fan.h" | ||||
|  | ||||
| @@ -16,7 +14,7 @@ class TemplateFan : public Component, public fan::Fan { | ||||
|   void set_has_direction(bool has_direction) { this->has_direction_ = has_direction; } | ||||
|   void set_has_oscillating(bool has_oscillating) { this->has_oscillating_ = has_oscillating; } | ||||
|   void set_speed_count(int count) { this->speed_count_ = count; } | ||||
|   void set_preset_modes(const std::initializer_list<std::string> &presets) { this->preset_modes_ = presets; } | ||||
|   void set_preset_modes(std::initializer_list<const char *> presets) { this->preset_modes_ = presets; } | ||||
|   fan::FanTraits get_traits() override { return this->traits_; } | ||||
|  | ||||
|  protected: | ||||
| @@ -26,7 +24,7 @@ class TemplateFan : public Component, public fan::Fan { | ||||
|   bool has_direction_{false}; | ||||
|   int speed_count_{0}; | ||||
|   fan::FanTraits traits_; | ||||
|   std::vector<std::string> preset_modes_{}; | ||||
|   std::vector<const char *> preset_modes_{}; | ||||
| }; | ||||
|  | ||||
| }  // namespace template_ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user