Browse Source

Made the code compatible with @oxan 's light-transformation branch.

oxan-light-transformation
Maurice Makaay 3 years ago
parent
commit
350d10b912
11 changed files with 131 additions and 103 deletions
  1. +0
    -1
      components/xiaomi_bslamp2/__init__.py
  2. +4
    -4
      components/xiaomi_bslamp2/binary_sensor/__init__.py
  3. +63
    -44
      components/xiaomi_bslamp2/light/__init__.py
  4. +2
    -1
      components/xiaomi_bslamp2/light/automation.h
  5. +3
    -18
      components/xiaomi_bslamp2/light/light_output.h
  6. +22
    -17
      components/xiaomi_bslamp2/light/light_transition.h
  7. +18
    -0
      components/xiaomi_bslamp2/light_hal.h
  8. +4
    -4
      components/xiaomi_bslamp2/output/__init__.py
  9. +4
    -4
      components/xiaomi_bslamp2/sensor/__init__.py
  10. +8
    -8
      components/xiaomi_bslamp2/text_sensor/__init__.py
  11. +3
    -2
      components/xiaomi_bslamp2/text_sensor/light_mode_text_sensor.h

+ 0
- 1
components/xiaomi_bslamp2/__init__.py View File

@ -4,7 +4,6 @@ from esphome import pins
from esphome.components.ledc.output import LEDCOutput
from esphome.components.gpio.output import GPIOBinaryOutput
from esphome.components.i2c import I2CComponent, I2CDevice
from esphome.core import coroutine
from esphome.core import CORE
from esphome.const import (
CONF_RED, CONF_GREEN, CONF_BLUE, CONF_WHITE, CONF_TRIGGER_PIN,


+ 4
- 4
components/xiaomi_bslamp2/binary_sensor/__init__.py View File

@ -54,11 +54,11 @@ CONFIG_SCHEMA = cv.All(
validate_binary_sensor,
)
def to_code(config):
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config)
yield binary_sensor.register_binary_sensor(var, config)
await cg.register_component(var, config)
await binary_sensor.register_binary_sensor(var, config)
front_panel_hal_var = yield cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID])
front_panel_hal_var = await cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID])
cg.add(var.set_parent(front_panel_hal_var))
cg.add(var.set_for(config[CONF_FOR]))

+ 63
- 44
components/xiaomi_bslamp2/light/__init__.py View File

@ -2,11 +2,12 @@ import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import light
from esphome import automation
from esphome.core import coroutine, Lambda
from esphome.core import Lambda
from esphome.const import (
CONF_RED, CONF_GREEN, CONF_BLUE, CONF_WHITE, CONF_COLOR_TEMPERATURE,
CONF_STATE, CONF_OUTPUT_ID, CONF_TRIGGER_ID, CONF_ID,
CONF_TRANSITION_LENGTH, CONF_BRIGHTNESS, CONF_EFFECT, CONF_FLASH_LENGTH
CONF_TRANSITION_LENGTH, CONF_BRIGHTNESS, CONF_EFFECT, CONF_FLASH_LENGTH,
CONF_TRANSITIONS, CONF_NAME
)
from .. import bslamp2_ns, CODEOWNERS, CONF_LIGHT_HAL_ID, LightHAL
@ -27,11 +28,13 @@ MIRED_MAX = 588
XiaomiBslamp2LightState = bslamp2_ns.class_("XiaomiBslamp2LightState", light.LightState)
XiaomiBslamp2LightOutput = bslamp2_ns.class_("XiaomiBslamp2LightOutput", light.LightOutput)
XiaomiBslamp2LightTransition = bslamp2_ns.class_("XiaomiBslamp2LightTransition", light.LightTransition)
PresetsContainer = bslamp2_ns.class_("PresetsContainer", cg.Component)
Preset = bslamp2_ns.class_("Preset", cg.Component)
BrightnessTrigger = bslamp2_ns.class_("BrightnessTrigger", automation.Trigger.template())
ActivatePresetAction = bslamp2_ns.class_("ActivatePresetAction", automation.Action)
DiscoAction = bslamp2_ns.class_("DiscoAction", automation.Action)
DiscoAction = bslamp2_ns.class_("DiscoAction", automation.Action)
PRESETS_SCHEMA = cv.Schema({
str.lower: cv.Schema({
@ -86,6 +89,9 @@ CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend(
cv.GenerateID(CONF_ID): cv.declare_id(XiaomiBslamp2LightState),
cv.GenerateID(CONF_LIGHT_HAL_ID): cv.use_id(LightHAL),
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(XiaomiBslamp2LightOutput),
cv.Optional(
CONF_TRANSITIONS, default=["bslamp2"]
): light.transitions.validate_transitions(XiaomiBslamp2LightOutput),
cv.Optional(CONF_ON_BRIGHTNESS): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(BrightnessTrigger),
@ -129,49 +135,49 @@ def maybe_simple_preset_action(schema):
@automation.register_action(
"light.disco_on", DiscoAction, light.automation.LIGHT_TURN_ON_ACTION_SCHEMA
)
def disco_action_on_to_code(config, action_id, template_arg, args):
light_var = yield cg.get_variable(config[CONF_ID])
async def disco_action_on_to_code(config, action_id, template_arg, args):
light_var = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, light_var)
if CONF_STATE in config:
template_ = yield cg.templatable(config[CONF_STATE], args, bool)
template_ = await cg.templatable(config[CONF_STATE], args, bool)
cg.add(var.set_state(template_))
if CONF_TRANSITION_LENGTH in config:
template_ = yield cg.templatable(
template_ = await cg.templatable(
config[CONF_TRANSITION_LENGTH], args, cg.uint32
)
cg.add(var.set_transition_length(template_))
if CONF_FLASH_LENGTH in config:
template_ = yield cg.templatable(config[CONF_FLASH_LENGTH], args, cg.uint32)
template_ = await cg.templatable(config[CONF_FLASH_LENGTH], args, cg.uint32)
cg.add(var.set_flash_length(template_))
if CONF_BRIGHTNESS in config:
template_ = yield cg.templatable(config[CONF_BRIGHTNESS], args, float)
template_ = await cg.templatable(config[CONF_BRIGHTNESS], args, float)
cg.add(var.set_brightness(template_))
if CONF_RED in config:
template_ = yield cg.templatable(config[CONF_RED], args, float)
template_ = await cg.templatable(config[CONF_RED], args, float)
cg.add(var.set_red(template_))
if CONF_GREEN in config:
template_ = yield cg.templatable(config[CONF_GREEN], args, float)
template_ = await cg.templatable(config[CONF_GREEN], args, float)
cg.add(var.set_green(template_))
if CONF_BLUE in config:
template_ = yield cg.templatable(config[CONF_BLUE], args, float)
template_ = await cg.templatable(config[CONF_BLUE], args, float)
cg.add(var.set_blue(template_))
if CONF_COLOR_TEMPERATURE in config:
template_ = yield cg.templatable(config[CONF_COLOR_TEMPERATURE], args, float)
template_ = await cg.templatable(config[CONF_COLOR_TEMPERATURE], args, float)
cg.add(var.set_color_temperature(template_))
if CONF_EFFECT in config:
template_ = yield cg.templatable(config[CONF_EFFECT], args, cg.std_string)
template_ = await cg.templatable(config[CONF_EFFECT], args, cg.std_string)
cg.add(var.set_effect(template_))
yield var
return var
@automation.register_action(
"light.disco_off", DiscoAction, light.automation.LIGHT_TURN_OFF_ACTION_SCHEMA
)
def disco_action_off_to_code(config, action_id, template_arg, args):
light_var = yield cg.get_variable(config[CONF_ID])
async def disco_action_off_to_code(config, action_id, template_arg, args):
light_var = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, light_var)
cg.add(var.set_disco_state(False))
yield var
return var
USED_PRESETS = []
@ -202,40 +208,54 @@ def register_preset_action(value):
register_preset_action
),
)
def preset_activate_to_code(config, action_id, template_arg, args):
presets_var = yield cg.get_variable(config[CONF_PRESETS_ID])
async def preset_activate_to_code(config, action_id, template_arg, args):
presets_var = await cg.get_variable(config[CONF_PRESETS_ID])
action_var = cg.new_Pvariable(action_id, template_arg, presets_var)
if CONF_NEXT in config:
cg.add(action_var.set_operation(f"next_{config[CONF_NEXT]}"))
elif CONF_PRESET in config:
cg.add(action_var.set_operation("activate_preset"))
group_template_ = yield cg.templatable(config[CONF_GROUP], args, cg.std_string)
group_template_ = await cg.templatable(config[CONF_GROUP], args, cg.std_string)
cg.add(action_var.set_group(group_template_))
preset_template_ = yield cg.templatable(config[CONF_PRESET], args, cg.std_string)
preset_template_ = await cg.templatable(config[CONF_PRESET], args, cg.std_string)
cg.add(action_var.set_preset(preset_template_))
else:
cg.add(action_var.set_operation("activate_group"))
group_template_ = yield cg.templatable(config[CONF_GROUP], args, cg.std_string)
group_template_ = await cg.templatable(config[CONF_GROUP], args, cg.std_string)
cg.add(action_var.set_group(group_template_))
yield action_var
return action_var
@light.transitions.register_output_transition(
XiaomiBslamp2LightOutput,
"bslamp2",
XiaomiBslamp2LightTransition,
"bslamp2",
{
cv.GenerateID(CONF_LIGHT_HAL_ID): cv.use_id(LightHAL),
},
)
async def bslamp2_transition_to_code(config, transition_id):
light_hal_var = await cg.get_variable(config[CONF_LIGHT_HAL_ID])
return cg.new_Pvariable(
transition_id,
config[CONF_NAME],
light_hal_var
)
@coroutine
def light_output_to_code(config):
async def light_output_to_code(config):
light_output_var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
yield light.register_light(light_output_var, config)
light_hal_var = yield cg.get_variable(config[CONF_LIGHT_HAL_ID])
await light.register_light(light_output_var, config)
light_hal_var = await cg.get_variable(config[CONF_LIGHT_HAL_ID])
cg.add(light_output_var.set_parent(light_hal_var))
@coroutine
def on_brightness_to_code(config):
light_output_var = yield cg.get_variable(config[CONF_OUTPUT_ID])
async def on_brightness_to_code(config):
light_hal_var = await cg.get_variable(config[CONF_LIGHT_HAL_ID])
for config in config.get(CONF_ON_BRIGHTNESS, []):
trigger = cg.new_Pvariable(config[CONF_TRIGGER_ID], light_output_var)
yield automation.build_automation(trigger, [(float, "x")], config)
trigger = cg.new_Pvariable(config[CONF_TRIGGER_ID], light_hal_var)
await automation.build_automation(trigger, [(float, "x")], config)
@coroutine
def preset_to_code(config, preset_group, preset_name):
light_var = yield cg.get_variable(config[CONF_ID])
async def preset_to_code(config, preset_group, preset_name):
light_var = await cg.get_variable(config[CONF_ID])
preset_var = cg.new_Pvariable(
config[CONF_PRESET_ID], light_var, preset_group, preset_name)
if CONF_TRANSITION_LENGTH in config:
@ -254,22 +274,21 @@ def preset_to_code(config, preset_group, preset_name):
cg.add(preset_var.set_effect(config[CONF_EFFECT]))
else:
cg.add(preset_var.set_effect("None"))
yield cg.register_component(preset_var, config)
return await cg.register_component(preset_var, config)
@coroutine
def presets_to_code(config):
async def presets_to_code(config):
presets_var = cg.new_Pvariable(config[CONF_PRESETS_ID])
yield cg.register_component(presets_var, config)
await cg.register_component(presets_var, config)
for preset_group, presets in config.get(CONF_PRESETS, {}).items():
for preset_name, preset_config in presets.items():
preset = yield preset_to_code(preset_config, preset_group, preset_name)
preset = await preset_to_code(preset_config, preset_group, preset_name)
cg.add(presets_var.add_preset(preset))
def to_code(config):
yield light_output_to_code(config)
yield on_brightness_to_code(config)
yield presets_to_code(config)
async def to_code(config):
await light_output_to_code(config)
await on_brightness_to_code(config)
await presets_to_code(config)
def validate(config):
valid_presets = config.get(CONF_PRESETS, {});


+ 2
- 1
components/xiaomi_bslamp2/light/automation.h View File

@ -3,6 +3,7 @@
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "interfaces.h"
#include "../light_hal.h"
#include "light_output.h"
#include "light_state.h"
#include "presets.h"
@ -14,7 +15,7 @@ namespace bslamp2 {
class BrightnessTrigger : public Trigger<float> {
public:
explicit BrightnessTrigger(XiaomiBslamp2LightOutput *parent) {
explicit BrightnessTrigger(LightHAL *parent) {
parent->add_on_state_callback([this](light::LightColorValues values) {
auto new_brightness = values.get_brightness();
if (values.get_state() == 0)


+ 3
- 18
components/xiaomi_bslamp2/light/light_output.h View File

@ -3,7 +3,7 @@
#include "../common.h"
#include "../light_hal.h"
#include "color_handler_chain.h"
#include "light_transformer.h"
#include "light_transition.h"
#include "esphome/core/component.h"
#include "esphome/components/ledc/ledc_output.h"
@ -35,19 +35,6 @@ class XiaomiBslamp2LightOutput : public Component, public light::LightOutput {
return traits;
}
std::unique_ptr<light::LightTransformer> create_default_transition() override {
return make_unique<XiaomiBslamp2LightTransitionTransformer>(
light_, light_mode_callback_, state_callback_);
}
void add_on_light_mode_callback(std::function<void(std::string)> &&callback) {
light_mode_callback_.add(std::move(callback));
}
void add_on_state_callback(std::function<void(light::LightColorValues)> &&callback) {
state_callback_.add(std::move(callback));
}
/**
* Applies a requested light state to the physicial GPIO outputs.
*/
@ -55,8 +42,8 @@ class XiaomiBslamp2LightOutput : public Component, public light::LightOutput {
auto values = state->current_values;
color_handler_chain->set_light_color_values(values);
light_mode_callback_.call(color_handler_chain->light_mode);
state_callback_.call(values);
light_->do_light_mode_callback(color_handler_chain->light_mode);
light_->do_state_callback(values);
// Note: one might think that it is more logical to turn on the LED
// circuitry master switch after setting the individual channels,
@ -76,8 +63,6 @@ class XiaomiBslamp2LightOutput : public Component, public light::LightOutput {
protected:
LightHAL *light_;
ColorHandler *color_handler_chain = new ColorHandlerChain();
CallbackManager<void(std::string)> light_mode_callback_{};
CallbackManager<void(light::LightColorValues)> state_callback_{};
};
} // namespace bslamp2


components/xiaomi_bslamp2/light/light_transformer.h → components/xiaomi_bslamp2/light/light_transition.h View File

@ -3,7 +3,8 @@
#include "../common.h"
#include "../light_hal.h"
#include "color_handler_chain.h"
#include "esphome/components/light/light_transformer.h"
#include "esphome/components/light/light_transition.h"
#include "esphome/components/light/transitions.h"
#include "esphome/components/light/light_color_values.h"
namespace esphome {
@ -11,19 +12,20 @@ namespace xiaomi {
namespace bslamp2 {
/**
* A LightTransitionTransformer class for the Xiaomi Mijia Bedside Lamp 2.
* A LightTransition class for the Xiaomi Mijia Bedside Lamp 2.
*/
class XiaomiBslamp2LightTransitionTransformer : public light::LightTransitionTransformer {
class XiaomiBslamp2LightTransition : public light::LightTransition {
public:
explicit XiaomiBslamp2LightTransitionTransformer(
LightHAL *light,
CallbackManager<void(std::string)> light_mode_callback,
CallbackManager<void(light::LightColorValues)> state_callback) :
light_(light),
light_mode_callback_(light_mode_callback),
state_callback_(state_callback) { }
explicit XiaomiBslamp2LightTransition(std::string name, LightHAL *light) :
light::LightTransition(name),
light_(light) { }
bool is_finished() override {
// TODO deprecate or compile for 2018.8.* only.
bool is_finished() {
return is_completed();
}
bool is_completed() override {
return force_finish_ || get_progress_() >= 1.0f;
}
@ -47,9 +49,9 @@ class XiaomiBslamp2LightTransitionTransformer : public light::LightTransitionTra
// 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_);
// code, these callbacks must be called from this transformer as well.
light_->do_light_mode_callback(end_->light_mode);
light_->do_state_callback(target_values_);
}
optional<light::LightColorValues> apply() override {
@ -62,7 +64,7 @@ class XiaomiBslamp2LightTransitionTransformer : public light::LightTransitionTra
}
// Otherwise perform a standard transformation.
else {
auto smoothed = light::LightTransitionTransformer::smoothed_progress(get_progress_());
auto smoothed = smoothed_progress_(get_progress_());
light_->set_rgbw(
esphome::lerp(smoothed, start_->red, end_->red),
esphome::lerp(smoothed, start_->green, end_->green),
@ -90,8 +92,11 @@ class XiaomiBslamp2LightTransitionTransformer : public light::LightTransitionTra
bool force_finish_{false};
GPIOOutputValues *start_ = new GPIOOutputValues();
ColorHandler *end_ = new ColorHandlerChain();
CallbackManager<void(std::string)> light_mode_callback_{};
CallbackManager<void(light::LightColorValues)> state_callback_{};
protected:
static float smoothed_progress_(float x) {
return x * x * x * (x * (x * 6.0f - 15.0f) + 10.0f);
}
};
} // namespace bslamp2

+ 18
- 0
components/xiaomi_bslamp2/light_hal.h View File

@ -45,6 +45,14 @@ class LightHAL : Component, public GPIOOutputValues {
void set_master1_pin(gpio::GPIOBinaryOutput *pin) { master1_pin_ = pin; }
void set_master2_pin(gpio::GPIOBinaryOutput *pin) { master2_pin_ = pin; }
void add_on_light_mode_callback(std::function<void(std::string)> &&callback) {
light_mode_callback_.add(std::move(callback));
}
void add_on_state_callback(std::function<void(light::LightColorValues)> &&callback) {
state_callback_.add(std::move(callback));
}
/**
* Turn on the master switch for the LEDs.
*/
@ -94,6 +102,14 @@ class LightHAL : Component, public GPIOOutputValues {
this->light_mode = light_mode;
}
void do_light_mode_callback(std::string light_mode) {
light_mode_callback_.call(light_mode);
}
void do_state_callback(light::LightColorValues values) {
state_callback_.call(values);
}
protected:
bool is_on_{false};
ledc::LEDCOutput *red_pin_;
@ -102,6 +118,8 @@ class LightHAL : Component, public GPIOOutputValues {
ledc::LEDCOutput *white_pin_;
gpio::GPIOBinaryOutput *master1_pin_;
gpio::GPIOBinaryOutput *master2_pin_;
CallbackManager<void(std::string)> light_mode_callback_{};
CallbackManager<void(light::LightColorValues)> state_callback_{};
};
} // namespace bslamp2


+ 4
- 4
components/xiaomi_bslamp2/output/__init__.py View File

@ -24,12 +24,12 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend(
}
).extend(cv.COMPONENT_SCHEMA)
def to_code(config):
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config)
yield output.register_output(var, config)
await cg.register_component(var, config)
await output.register_output(var, config)
front_panel_hal_var = yield cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID])
front_panel_hal_var = await cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID])
cg.add(var.set_parent(front_panel_hal_var))
def maybe_simple_level_value(schema):


+ 4
- 4
components/xiaomi_bslamp2/sensor/__init__.py View File

@ -22,12 +22,12 @@ CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend(
}
).extend(cv.COMPONENT_SCHEMA)
def to_code(config):
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config)
yield sensor.register_sensor(var, config)
await cg.register_component(var, config)
await sensor.register_sensor(var, config)
front_panel_hal_var = yield cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID])
front_panel_hal_var = await cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID])
cg.add(var.set_parent(front_panel_hal_var))
cg.add(var.set_range_from(config[CONF_RANGE_FROM]))
cg.add(var.set_range_to(config[CONF_RANGE_TO]))

+ 8
- 8
components/xiaomi_bslamp2/text_sensor/__init__.py View File

@ -1,9 +1,9 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import text_sensor
from esphome.const import CONF_ID, CONF_OUTPUT_ID
from .. import bslamp2_ns, CODEOWNERS
from ..light import XiaomiBslamp2LightOutput
from esphome.const import CONF_ID
from .. import bslamp2_ns, CODEOWNERS, CONF_LIGHT_HAL_ID
from ..light import LightHAL
DEPENDENCIES = ["xiaomi_bslamp2"]
@ -16,15 +16,15 @@ XiaomiBslamp2LightModeTextSensor = bslamp2_ns.class_(
CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(XiaomiBslamp2LightModeTextSensor),
cv.GenerateID(CONF_OUTPUT_ID): cv.use_id(XiaomiBslamp2LightOutput),
cv.GenerateID(CONF_LIGHT_HAL_ID): cv.use_id(LightHAL),
}
).extend(cv.COMPONENT_SCHEMA)
def to_code(config):
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config)
yield text_sensor.register_text_sensor(var, config)
await cg.register_component(var, config)
await text_sensor.register_text_sensor(var, config)
parent_var = yield cg.get_variable(config[CONF_OUTPUT_ID])
parent_var = await cg.get_variable(config[CONF_LIGHT_HAL_ID])
cg.add(var.set_parent(parent_var))

+ 3
- 2
components/xiaomi_bslamp2/text_sensor/light_mode_text_sensor.h View File

@ -1,6 +1,7 @@
#pragma once
#include "esphome/components/text_sensor/text_sensor.h"
#include "../light_hal.h"
namespace esphome {
namespace xiaomi {
@ -14,7 +15,7 @@ namespace bslamp2 {
*/
class XiaomiBslamp2LightModeTextSensor : public text_sensor::TextSensor, public Component {
public:
void set_parent(XiaomiBslamp2LightOutput *light) { light_ = light; }
void set_parent(LightHAL *light) { light_ = light; }
void setup() {
light_->add_on_light_mode_callback([this](std::string light_mode) {
@ -26,7 +27,7 @@ class XiaomiBslamp2LightModeTextSensor : public text_sensor::TextSensor, public
}
protected:
XiaomiBslamp2LightOutput *light_;
LightHAL *light_;
std::string last_light_mode_ = LIGHT_MODE_UNKNOWN;
};


Loading…
Cancel
Save