#pragma once #include "../common.h" #include "../light_hal.h" #include "color_instant_handler.h" #include "light_transformer.h" #include "esphome/components/ledc/ledc_output.h" namespace esphome { namespace xiaomi { namespace bslamp2 { /** * A LightOutput class for the Xiaomi Mijia Bedside Lamp 2. * * The function of this class is to translate a required light state * into actual physicial GPIO output signals to drive the device's LED * circuitry. It forms the glue between the physical device and the * logical light color input. */ class XiaomiBslamp2LightOutput : public Component, public light::LightOutput { public: void set_parent(LightHAL *light) { light_ = light; } /** * Returns a LightTraits object, which is used to explain to the outside * world (e.g. Home Assistant) what features are supported by this device. */ light::LightTraits get_traits() override { auto traits = light::LightTraits(); #ifdef HAS_COLOR_MODES traits.set_supported_color_modes({light::ColorMode::RGB, light::ColorMode::COLOR_TEMPERATURE}); #else traits.set_supports_rgb(true); traits.set_supports_color_temperature(true); traits.set_supports_brightness(true); traits.set_supports_rgb_white_value(false); traits.set_supports_color_interlock(true); #endif traits.set_min_mireds(MIRED_MIN); traits.set_max_mireds(MIRED_MAX); return traits; } std::unique_ptr create_default_transition() override { return make_unique(light_); } void add_on_light_mode_callback(std::function &&callback) { light_mode_callback_.add(std::move(callback)); } void add_on_state_callback(std::function &&callback) { state_callback_.add(std::move(callback)); } /** * Applies a requested light state to the physicial GPIO outputs. */ void write_state(light::LightState *state) { auto values = state->current_values; // The color must either be set instantly, or the color is // transitioning to an end color. The transition handler will do its // own inspection to see if a transition is currently active or not. // Based on the outcome, use either the instant or transition handler. //GPIOOutputs *delegate; //if (transition_handler_->set_light_color_values(values)) { // delegate = transition_handler_; // light_mode_callback_.call(delegate->light_mode); // state_callback_.call(transition_handler_->get_end_values()); //} else { instant_handler_->set_light_color_values(values); //delegate = instant_handler_; light_mode_callback_.call(instant_handler_->light_mode); state_callback_.call(values); //} // Note: one might think that it is more logical to turn on the LED // circuitry master switch after setting the individual channels, // but this is the order that was used by the original firmware. I // tried to stay as close as possible to the original behavior, so // that's why these GPIOs are turned on at this point. if (values.get_state() != 0) light_->turn_on(); // Apply the current GPIO output levels from the selected handler. light_->set_rgbw( instant_handler_->red, instant_handler_->green, instant_handler_->blue, instant_handler_->white); if (values.get_state() == 0) light_->turn_off(); } protected: LightHAL *light_; ColorInstantHandler *instant_handler_ = new ColorInstantHandler(); CallbackManager light_mode_callback_{}; CallbackManager state_callback_{}; }; } // namespace bslamp2 } // namespace xiaomi } // namespace esphome