You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
3.5 KiB

  1. #pragma once
  2. #include "../common.h"
  3. #include "../light_hal.h"
  4. #include "color_handler_chain.h"
  5. #include "esphome/components/light/light_transformer.h"
  6. #include "esphome/components/light/light_color_values.h"
  7. namespace esphome {
  8. namespace xiaomi {
  9. namespace bslamp2 {
  10. /**
  11. * A LightTransitionTransformer class for the Xiaomi Mijia Bedside Lamp 2.
  12. */
  13. class XiaomiBslamp2LightTransitionTransformer : public light::LightTransitionTransformer {
  14. public:
  15. explicit XiaomiBslamp2LightTransitionTransformer(
  16. LightHAL *light,
  17. CallbackManager<void(std::string)> light_mode_callback,
  18. CallbackManager<void(light::LightColorValues)> state_callback) :
  19. light_(light),
  20. light_mode_callback_(light_mode_callback),
  21. state_callback_(state_callback) { }
  22. bool is_finished() override {
  23. return force_finish_ || get_progress_() >= 1.0f;
  24. }
  25. void start() override {
  26. // Determine the GPIO outputs to use for the start and end point.
  27. // This light transition transformer will then transition linearly between them.
  28. light_->copy_to(&start_);
  29. end_.set_light_color_values(target_values_);
  30. // Update the light mode of the light HAL to the target state, unless
  31. // this is night mode. For night mode, the update is done after the
  32. // state has been reached. This makes sure that forcing instant
  33. // transitions for night light to night light is only done when the
  34. // night light status has actually been reached. E.g. when in RGB mode
  35. // and transitioning to night light in 10 seconds, interrupting this
  36. // after 5 seconds with a new night light setting should not make the
  37. // transition instant.
  38. if (end_.light_mode != LIGHT_MODE_NIGHT) {
  39. light_->set_light_mode(end_.light_mode);
  40. }
  41. // Run callbacks. These are normally called from the LightOutput, but
  42. // since I don't call LightOutput::write_state() from this transformer's
  43. // code, these callbacks must be called from this transformer instead.
  44. light_mode_callback_.call(end_.light_mode);
  45. state_callback_.call(target_values_);
  46. }
  47. optional<light::LightColorValues> apply() override {
  48. // When transitioning between night mode light colors, then do this immediately.
  49. // The LED driver circuitry is not capable of doing clean color or brightness
  50. // transitions at the low levels as used for the night light.
  51. if (end_.light_mode == LIGHT_MODE_NIGHT && start_.light_mode == LIGHT_MODE_NIGHT) {
  52. light_->set_state(&end_);
  53. force_finish_ = true;
  54. }
  55. // Otherwise perform a standard transformation.
  56. else {
  57. auto smoothed = light::LightTransitionTransformer::smoothed_progress(get_progress_());
  58. light_->set_rgbw(
  59. esphome::lerp(smoothed, start_.red, end_.red),
  60. esphome::lerp(smoothed, start_.green, end_.green),
  61. esphome::lerp(smoothed, start_.blue, end_.blue),
  62. esphome::lerp(smoothed, start_.white, end_.white));
  63. if (end_.light_mode != LIGHT_MODE_OFF) {
  64. light_->turn_on();
  65. }
  66. }
  67. if (is_finished()) {
  68. light_->set_light_mode(end_.light_mode);
  69. if (end_.light_mode == LIGHT_MODE_OFF) {
  70. light_->turn_off();
  71. }
  72. return target_values_;
  73. } else {
  74. return {};
  75. }
  76. }
  77. protected:
  78. LightHAL *light_;
  79. bool force_finish_{false};
  80. GPIOOutputValues start_{};
  81. ColorHandlerChain end_{};
  82. CallbackManager<void(std::string)> light_mode_callback_{};
  83. CallbackManager<void(light::LightColorValues)> state_callback_{};
  84. };
  85. } // namespace bslamp2
  86. } // namespace xiaomi
  87. } // namespace esphome