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.

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