diff --git a/CHANGELOG.md b/CHANGELOG.md index c04fb29..9812ff1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2021.8.1] + +**Note**: This release requires ESPHome 2021.8.0 and Home Assistant 2021.8.0 or newer. + +### Changed +- Fixed transitioning from the off to on state. Thanks to @marcel1988 for informing + me about his non-functional wake-up light script. Before this fix, the light would + stay off during the full transformation, only to turn on at the very end. +- The `on_brightness` trigger is now also called at the start of a transition. + This fixes a problem with the brightness slider illumination not following along + when you slide your finger over it. +- Suppressing a transition time for transitioning to a night light color is now + only instant when starting from a night light setting. Before this change, moving + from for example 80% brightness to 1% brightness (i.e. night light), would be + instant. Now an actual transformation is done. + ## [2021.8.0] **Note**: This release requires ESPHome 2021.8.0 and Home Assistant 2021.8.0 or newer. diff --git a/components/xiaomi_bslamp2/light/color_handler_off.h b/components/xiaomi_bslamp2/light/color_handler_off.h index 527df28..64f6042 100644 --- a/components/xiaomi_bslamp2/light/color_handler_off.h +++ b/components/xiaomi_bslamp2/light/color_handler_off.h @@ -9,7 +9,7 @@ namespace xiaomi { namespace bslamp2 { /** - * This class can handle the GPIO outputs in case the light of turned off. + * This class can handle the GPIO outputs in case the light is turned off. */ class ColorHandlerOff : public ColorHandler { public: diff --git a/components/xiaomi_bslamp2/light/light_output.h b/components/xiaomi_bslamp2/light/light_output.h index 7d14e79..7d717e3 100644 --- a/components/xiaomi_bslamp2/light/light_output.h +++ b/components/xiaomi_bslamp2/light/light_output.h @@ -36,7 +36,8 @@ class XiaomiBslamp2LightOutput : public Component, public light::LightOutput { } std::unique_ptr create_default_transition() override { - return make_unique(light_); + return make_unique( + light_, light_mode_callback_, state_callback_); } void add_on_light_mode_callback(std::function &&callback) { diff --git a/components/xiaomi_bslamp2/light/light_transformer.h b/components/xiaomi_bslamp2/light/light_transformer.h index c70d631..f78dba4 100644 --- a/components/xiaomi_bslamp2/light/light_transformer.h +++ b/components/xiaomi_bslamp2/light/light_transformer.h @@ -15,25 +15,52 @@ namespace bslamp2 { */ class XiaomiBslamp2LightTransitionTransformer : public light::LightTransitionTransformer { public: - explicit XiaomiBslamp2LightTransitionTransformer(LightHAL *light) : light_(light) { } + explicit XiaomiBslamp2LightTransitionTransformer( + LightHAL *light, + CallbackManager light_mode_callback, + CallbackManager state_callback) : + light_(light), + light_mode_callback_(light_mode_callback), + state_callback_(state_callback) { } bool is_finished() override { return force_finish_ || get_progress_() >= 1.0f; } void start() override { - // Compute the GPIO outputs to use for the end point. - // This light transition transformer will then transition linearly between - // the current GPIO outputs and the target ones. + // Determine the GPIO outputs to use for the start and end point. + // This light transition transformer will then transition linearly between them. light_->copy_to(start_); end_->set_light_color_values(target_values_); + + // Update the light mode of the light HAL to the target state, unless + // this is night mode. For night mode, the update is done after the + // state has been reached. This makes sure that forcing instant + // transitions for night light to night light is only done when the + // night light status has actually been reached. E.g. when in RGB mode + // and transitioning to night light in 10 seconds, interrupting this + // after 5 seconds with a new night light setting should not make the + // transition instant. + if (end_->light_mode != LIGHT_MODE_NIGHT) { + light_->set_light_mode(end_->light_mode); + } + + // Run callbacks. These are normally called from the LightOutput, but + // since I don't call LightOutput::write_state() from this transformer's + // code, these callbacks must be called from this transformer instead. + light_mode_callback_.call(end_->light_mode); + state_callback_.call(target_values_); } optional apply() override { - if (end_->light_mode == "night") { + // When transitioning between night mode light colors, then do this immediately. + // The LED driver circuitry is not capable of doing clean color or brightness + // transitions at the low levels as used for the night light. + if (end_->light_mode == LIGHT_MODE_NIGHT && start_->light_mode == LIGHT_MODE_NIGHT) { light_->set_state(end_); force_finish_ = true; } + // Otherwise perform a standard transformation. else { auto smoothed = light::LightTransitionTransformer::smoothed_progress(get_progress_()); light_->set_rgbw( @@ -41,9 +68,17 @@ class XiaomiBslamp2LightTransitionTransformer : public light::LightTransitionTra esphome::lerp(smoothed, start_->green, end_->green), esphome::lerp(smoothed, start_->blue, end_->blue), esphome::lerp(smoothed, start_->white, end_->white)); + if (end_->light_mode != LIGHT_MODE_OFF) { + light_->turn_on(); + } } if (is_finished()) { + light_->set_light_mode(end_->light_mode); + if (end_->light_mode == LIGHT_MODE_OFF) { + light_->turn_off(); + } + return target_values_; } else { return {}; @@ -52,9 +87,11 @@ class XiaomiBslamp2LightTransitionTransformer : public light::LightTransitionTra protected: LightHAL *light_; - bool force_finish_ = false; + bool force_finish_{false}; GPIOOutputValues *start_ = new GPIOOutputValues(); ColorHandler *end_ = new ColorHandlerChain(); + CallbackManager light_mode_callback_{}; + CallbackManager state_callback_{}; }; } // namespace bslamp2 diff --git a/components/xiaomi_bslamp2/light_hal.h b/components/xiaomi_bslamp2/light_hal.h index dfeff8c..ee0ac91 100644 --- a/components/xiaomi_bslamp2/light_hal.h +++ b/components/xiaomi_bslamp2/light_hal.h @@ -51,6 +51,7 @@ class LightHAL : Component, public GPIOOutputValues { void turn_on() { master1_pin_->turn_on(); master2_pin_->turn_on(); + is_on_ = true; } /** @@ -59,6 +60,14 @@ class LightHAL : Component, public GPIOOutputValues { void turn_off() { master1_pin_->turn_off(); master2_pin_->turn_off(); + is_on_ = false; + } + + /** + * Check if the light is turned on. + */ + bool is_on() { + return is_on_; } void set_state(GPIOOutputValues *new_state) { @@ -81,7 +90,12 @@ class LightHAL : Component, public GPIOOutputValues { this->white = w; } + void set_light_mode(std::string light_mode) { + this->light_mode = light_mode; + } + protected: + bool is_on_{false}; ledc::LEDCOutput *red_pin_; ledc::LEDCOutput *green_pin_; ledc::LEDCOutput *blue_pin_; diff --git a/doc/testplan.md b/doc/testplan.md index 8de87f5..0274e69 100644 --- a/doc/testplan.md +++ b/doc/testplan.md @@ -56,10 +56,15 @@ been introduced. * Go to Home Assistant and check: * if you can turn on/off the lamp * if you can select colors from the RGB color model - * if you can select colors from the white light color temperature model + * if you can select colors from the Color Temperature model * if you can set the brightness of the lamp * if selecting the lowest possible brightness results in the lamp switching to "night light" mode + * if a transition from off to on with a long transition time works (e.g. 10s) + * if a transition from on to off with a long transition time works + * if a transition from night light to some bright light (e.g. 10s) can be + interrupted by a transition back to night light (e.g. after 5 seconds), + resulting in a transition back (not an instant drop to night light) ## Step 3: Release the new version