mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-29 22:24:26 +00:00 
			
		
		
		
	Refactor fan platform to resemble climate/cover platforms (#2848)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl> Co-authored-by: rob-deutsch <robzyb+altgithub@gmail.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -17,7 +17,7 @@ from .. import hbridge_ns | ||||
| CODEOWNERS = ["@WeekendWarrior"] | ||||
|  | ||||
|  | ||||
| HBridgeFan = hbridge_ns.class_("HBridgeFan", fan.FanState) | ||||
| HBridgeFan = hbridge_ns.class_("HBridgeFan", cg.Component, fan.Fan) | ||||
|  | ||||
| DecayMode = hbridge_ns.enum("DecayMode") | ||||
| DECAY_MODE_OPTIONS = { | ||||
| @@ -59,6 +59,7 @@ async def to_code(config): | ||||
|         config[CONF_SPEED_COUNT], | ||||
|         config[CONF_DECAY_MODE], | ||||
|     ) | ||||
|     await cg.register_component(var, config) | ||||
|     await fan.register_fan(var, config) | ||||
|     pin_a_ = await cg.get_variable(config[CONF_PIN_A]) | ||||
|     cg.add(var.set_pin_a(pin_a_)) | ||||
|   | ||||
| @@ -22,47 +22,49 @@ void HBridgeFan::set_hbridge_levels_(float a_level, float b_level, float enable) | ||||
|   ESP_LOGD(TAG, "Setting speed: a: %.2f, b: %.2f, enable: %.2f", a_level, b_level, enable); | ||||
| } | ||||
|  | ||||
| fan::FanStateCall HBridgeFan::brake() { | ||||
| fan::FanCall HBridgeFan::brake() { | ||||
|   ESP_LOGD(TAG, "Braking"); | ||||
|   (this->enable_ == nullptr) ? this->set_hbridge_levels_(1.0f, 1.0f) : this->set_hbridge_levels_(1.0f, 1.0f, 1.0f); | ||||
|   return this->make_call().set_state(false); | ||||
| } | ||||
|  | ||||
| void HBridgeFan::setup() { | ||||
|   auto restore = this->restore_state_(); | ||||
|   if (restore.has_value()) { | ||||
|     restore->apply(*this); | ||||
|     this->write_state_(); | ||||
|   } | ||||
| } | ||||
| void HBridgeFan::dump_config() { | ||||
|   ESP_LOGCONFIG(TAG, "Fan '%s':", this->get_name().c_str()); | ||||
|   if (this->get_traits().supports_oscillation()) { | ||||
|     ESP_LOGCONFIG(TAG, "  Oscillation: YES"); | ||||
|   } | ||||
|   if (this->get_traits().supports_direction()) { | ||||
|     ESP_LOGCONFIG(TAG, "  Direction: YES"); | ||||
|   } | ||||
|   LOG_FAN("", "H-Bridge Fan", this); | ||||
|   if (this->decay_mode_ == DECAY_MODE_SLOW) { | ||||
|     ESP_LOGCONFIG(TAG, "  Decay Mode: Slow"); | ||||
|   } else { | ||||
|     ESP_LOGCONFIG(TAG, "  Decay Mode: Fast"); | ||||
|   } | ||||
| } | ||||
| void HBridgeFan::setup() { | ||||
|   auto traits = fan::FanTraits(this->oscillating_ != nullptr, true, true, this->speed_count_); | ||||
|   this->set_traits(traits); | ||||
|   this->add_on_state_callback([this]() { this->next_update_ = true; }); | ||||
| fan::FanTraits HBridgeFan::get_traits() { | ||||
|   return fan::FanTraits(this->oscillating_ != nullptr, true, true, this->speed_count_); | ||||
| } | ||||
| void HBridgeFan::loop() { | ||||
|   if (!this->next_update_) { | ||||
|     return; | ||||
|   } | ||||
|   this->next_update_ = false; | ||||
| void HBridgeFan::control(const fan::FanCall &call) { | ||||
|   if (call.get_state().has_value()) | ||||
|     this->state = *call.get_state(); | ||||
|   if (call.get_speed().has_value()) | ||||
|     this->speed = *call.get_speed(); | ||||
|   if (call.get_oscillating().has_value()) | ||||
|     this->oscillating = *call.get_oscillating(); | ||||
|   if (call.get_direction().has_value()) | ||||
|     this->direction = *call.get_direction(); | ||||
|  | ||||
|   float speed = 0.0f; | ||||
|   if (this->state) { | ||||
|     speed = static_cast<float>(this->speed) / static_cast<float>(this->speed_count_); | ||||
|   } | ||||
|   this->write_state_(); | ||||
|   this->publish_state(); | ||||
| } | ||||
| void HBridgeFan::write_state_() { | ||||
|   float speed = this->state ? static_cast<float>(this->speed) / static_cast<float>(this->speed_count_) : 0.0f; | ||||
|   if (speed == 0.0f) {  // off means idle | ||||
|     (this->enable_ == nullptr) ? this->set_hbridge_levels_(speed, speed) | ||||
|                                : this->set_hbridge_levels_(speed, speed, speed); | ||||
|     return; | ||||
|   } | ||||
|   if (this->direction == fan::FAN_DIRECTION_FORWARD) { | ||||
|   } else if (this->direction == fan::FanDirection::FORWARD) { | ||||
|     if (this->decay_mode_ == DECAY_MODE_SLOW) { | ||||
|       (this->enable_ == nullptr) ? this->set_hbridge_levels_(1.0f - speed, 1.0f) | ||||
|                                  : this->set_hbridge_levels_(1.0f - speed, 1.0f, 1.0f); | ||||
| @@ -79,6 +81,9 @@ void HBridgeFan::loop() { | ||||
|                                  : this->set_hbridge_levels_(1.0f, 0.0f, speed); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (this->oscillating_ != nullptr) | ||||
|     this->oscillating_->set_state(this->oscillating); | ||||
| } | ||||
|  | ||||
| }  // namespace hbridge | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| #include "esphome/core/automation.h" | ||||
| #include "esphome/components/output/binary_output.h" | ||||
| #include "esphome/components/output/float_output.h" | ||||
| #include "esphome/components/fan/fan_state.h" | ||||
| #include "esphome/components/fan/fan.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace hbridge { | ||||
| @@ -13,7 +13,7 @@ enum DecayMode { | ||||
|   DECAY_MODE_FAST = 1, | ||||
| }; | ||||
|  | ||||
| class HBridgeFan : public fan::FanState { | ||||
| class HBridgeFan : public Component, public fan::Fan { | ||||
|  public: | ||||
|   HBridgeFan(int speed_count, DecayMode decay_mode) : speed_count_(speed_count), decay_mode_(decay_mode) {} | ||||
|  | ||||
| @@ -22,25 +22,22 @@ class HBridgeFan : public fan::FanState { | ||||
|   void set_enable_pin(output::FloatOutput *enable) { enable_ = enable; } | ||||
|  | ||||
|   void setup() override; | ||||
|   void loop() override; | ||||
|   void dump_config() override; | ||||
|   float get_setup_priority() const override { return setup_priority::HARDWARE; } | ||||
|   fan::FanTraits get_traits() override; | ||||
|  | ||||
|   fan::FanStateCall brake(); | ||||
|  | ||||
|   int get_speed_count() { return this->speed_count_; } | ||||
|   // update Hbridge without a triggered FanState change, eg. for acceleration/deceleration ramping | ||||
|   void internal_update() { this->next_update_ = true; } | ||||
|   fan::FanCall brake(); | ||||
|  | ||||
|  protected: | ||||
|   output::FloatOutput *pin_a_; | ||||
|   output::FloatOutput *pin_b_; | ||||
|   output::FloatOutput *enable_{nullptr}; | ||||
|   output::BinaryOutput *oscillating_{nullptr}; | ||||
|   bool next_update_{true}; | ||||
|   int speed_count_{}; | ||||
|   DecayMode decay_mode_{DECAY_MODE_SLOW}; | ||||
|  | ||||
|   void control(const fan::FanCall &call) override; | ||||
|   void write_state_(); | ||||
|  | ||||
|   void set_hbridge_levels_(float a_level, float b_level); | ||||
|   void set_hbridge_levels_(float a_level, float b_level, float enable); | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user