ESPHome  2022.9.1
transformers.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include "esphome/core/helpers.h"
5 #include "light_color_values.h"
6 #include "light_state.h"
7 #include "light_transformer.h"
8 
9 namespace esphome {
10 namespace light {
11 
13  public:
14  void start() override {
15  // When turning light on from off state, use target state and only increase brightness from zero.
16  if (!this->start_values_.is_on() && this->target_values_.is_on()) {
18  this->start_values_.set_brightness(0.0f);
19  }
20 
21  // When turning light off from on state, use source state and only decrease brightness to zero. Use a second
22  // variable for transition end state, as overwriting target_values breaks LightState logic.
23  if (this->start_values_.is_on() && !this->target_values_.is_on()) {
25  this->end_values_.set_brightness(0.0f);
26  } else {
28  }
29 
30  // When changing color mode, go through off state, as color modes are orthogonal and there can't be two active.
32  this->changing_color_mode_ = true;
33  this->intermediate_values_ = this->start_values_;
34  this->intermediate_values_.set_state(false);
35  }
36  }
37 
39  float p = this->get_progress_();
40 
41  // Halfway through, when intermediate state (off) is reached, flip it to the target, but remain off.
42  if (this->changing_color_mode_ && p > 0.5f &&
45  this->intermediate_values_.set_state(false);
46  }
47 
49  LightColorValues &end = this->changing_color_mode_ && p < 0.5f ? this->intermediate_values_ : this->end_values_;
50  if (this->changing_color_mode_)
51  p = p < 0.5f ? p * 2 : (p - 0.5) * 2;
52 
54  return LightColorValues::lerp(start, end, v);
55  }
56 
57  protected:
58  // This looks crazy, but it reduces to 6x^5 - 15x^4 + 10x^3 which is just a smooth sigmoid-like
59  // transition from 0 to 1 on x = [0, 1]
60  static float smoothed_progress(float x) { return x * x * x * (x * (x * 6.0f - 15.0f) + 10.0f); }
61 
62  bool changing_color_mode_{false};
65 };
66 
68  public:
69  LightFlashTransformer(LightState &state) : state_(state) {}
70 
71  void start() override {
72  this->transition_length_ = this->state_.get_flash_transition_length();
73  if (this->transition_length_ * 2 > this->length_)
74  this->transition_length_ = this->length_ / 2;
75 
76  this->begun_lightstate_restore_ = false;
77 
78  // first transition to original target
79  this->transformer_ = this->state_.get_output()->create_default_transition();
80  this->transformer_->setup(this->state_.current_values, this->target_values_, this->transition_length_);
81  }
82 
84  optional<LightColorValues> result = {};
85 
86  if (this->transformer_ == nullptr && millis() > this->start_time_ + this->length_ - this->transition_length_) {
87  // second transition back to start value
88  this->transformer_ = this->state_.get_output()->create_default_transition();
89  this->transformer_->setup(this->state_.current_values, this->get_start_values(), this->transition_length_);
90  this->begun_lightstate_restore_ = true;
91  }
92 
93  if (this->transformer_ != nullptr) {
94  result = this->transformer_->apply();
95 
96  if (this->transformer_->is_finished()) {
97  this->transformer_->stop();
98  this->transformer_ = nullptr;
99  }
100  }
101 
102  return result;
103  }
104 
105  // Restore the original values after the flash.
106  void stop() override {
107  if (this->transformer_ != nullptr) {
108  this->transformer_->stop();
109  this->transformer_ = nullptr;
110  }
111  this->state_.current_values = this->get_start_values();
112  this->state_.remote_values = this->get_start_values();
113  this->state_.publish_state();
114  }
115 
116  bool is_finished() override { return this->begun_lightstate_restore_ && LightTransformer::is_finished(); }
117 
118  protected:
121  std::unique_ptr<LightTransformer> transformer_{nullptr};
123 };
124 
125 } // namespace light
126 } // namespace esphome
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Definition: light_state.h:32
bool is_on() const
Get the binary true/false state of these light color values.
float get_progress_()
The progress of this transition, on a scale of 0 to 1.
void set_state(float state)
Set the state of these light color values. In range from 0.0 (off) to 1.0 (on)
Base class for all light color transformers, such as transitions or flashes.
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:26
LightFlashTransformer(LightState &state)
Definition: transformers.h:69
This class represents the color state for a light object.
optional< LightColorValues > apply() override
Definition: transformers.h:83
optional< LightColorValues > apply() override
Definition: transformers.h:38
ColorMode get_color_mode() const
Get the color mode of these light color values.
const LightColorValues & get_start_values() const
void set_brightness(float brightness)
Set the brightness property of these light color values. In range 0.0 to 1.0.
Definition: a4988.cpp:4
virtual bool is_finished()
Indicates whether this transformation is finished.
static LightColorValues lerp(const LightColorValues &start, const LightColorValues &end, float completion)
Linearly interpolate between the values in start to the values in end.
bool state
Definition: fan.h:34