mirror of
https://github.com/esphome/esphome.git
synced 2024-11-23 15:38:11 +01:00
WIP: "off" color temperature for (rgb)ct lights
Some (rgb)ct lights require a certain color temperature to be set to actually turn off (the white component, in case of rgbct lights), this allows configuring that.
This commit is contained in:
parent
964410bd64
commit
945c41aa3b
8 changed files with 67 additions and 11 deletions
|
@ -13,11 +13,13 @@ class CTLightOutput : public light::LightOutput {
|
||||||
void set_brightness(output::FloatOutput *brightness) { brightness_ = brightness; }
|
void set_brightness(output::FloatOutput *brightness) { brightness_ = brightness; }
|
||||||
void set_cold_white_temperature(float cold_white_temperature) { cold_white_temperature_ = cold_white_temperature; }
|
void set_cold_white_temperature(float cold_white_temperature) { cold_white_temperature_ = cold_white_temperature; }
|
||||||
void set_warm_white_temperature(float warm_white_temperature) { warm_white_temperature_ = warm_white_temperature; }
|
void set_warm_white_temperature(float warm_white_temperature) { warm_white_temperature_ = warm_white_temperature; }
|
||||||
|
void set_off_color_temperature(float off_color_temperature) { off_color_temperature_ = off_color_temperature; }
|
||||||
light::LightTraits get_traits() override {
|
light::LightTraits get_traits() override {
|
||||||
auto traits = light::LightTraits();
|
auto traits = light::LightTraits();
|
||||||
traits.set_supported_color_modes({light::ColorMode::COLOR_TEMPERATURE});
|
traits.set_supported_color_modes({light::ColorMode::COLOR_TEMPERATURE});
|
||||||
traits.set_min_mireds(this->cold_white_temperature_);
|
traits.set_min_mireds(this->cold_white_temperature_);
|
||||||
traits.set_max_mireds(this->warm_white_temperature_);
|
traits.set_max_mireds(this->warm_white_temperature_);
|
||||||
|
traits.set_off_mireds(this->off_color_temperature_);
|
||||||
return traits;
|
return traits;
|
||||||
}
|
}
|
||||||
void write_state(light::LightState *state) override {
|
void write_state(light::LightState *state) override {
|
||||||
|
@ -32,6 +34,7 @@ class CTLightOutput : public light::LightOutput {
|
||||||
output::FloatOutput *brightness_;
|
output::FloatOutput *brightness_;
|
||||||
float cold_white_temperature_;
|
float cold_white_temperature_;
|
||||||
float warm_white_temperature_;
|
float warm_white_temperature_;
|
||||||
|
float off_color_temperature_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace color_temperature
|
} // namespace color_temperature
|
||||||
|
|
|
@ -7,6 +7,9 @@ from esphome.const import (
|
||||||
CONF_OUTPUT_ID,
|
CONF_OUTPUT_ID,
|
||||||
CONF_COLD_WHITE_COLOR_TEMPERATURE,
|
CONF_COLD_WHITE_COLOR_TEMPERATURE,
|
||||||
CONF_WARM_WHITE_COLOR_TEMPERATURE,
|
CONF_WARM_WHITE_COLOR_TEMPERATURE,
|
||||||
|
CONF_OFF_COLOR_TEMPERATURE,
|
||||||
|
CONF_COLD_WHITE,
|
||||||
|
CONF_WARM_WHITE,
|
||||||
)
|
)
|
||||||
|
|
||||||
CODEOWNERS = ["@jesserockz"]
|
CODEOWNERS = ["@jesserockz"]
|
||||||
|
@ -22,6 +25,12 @@ CONFIG_SCHEMA = cv.All(
|
||||||
cv.Required(CONF_BRIGHTNESS): cv.use_id(output.FloatOutput),
|
cv.Required(CONF_BRIGHTNESS): cv.use_id(output.FloatOutput),
|
||||||
cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
|
cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
|
||||||
cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
|
cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
|
||||||
|
cv.Optional(CONF_OFF_COLOR_TEMPERATURE): cv.enum(
|
||||||
|
{
|
||||||
|
CONF_COLD_WHITE: None,
|
||||||
|
CONF_WARM_WHITE: None,
|
||||||
|
}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
light.validate_color_temperature_channels,
|
light.validate_color_temperature_channels,
|
||||||
|
@ -40,3 +49,13 @@ async def to_code(config):
|
||||||
|
|
||||||
cg.add(var.set_cold_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE]))
|
cg.add(var.set_cold_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE]))
|
||||||
cg.add(var.set_warm_white_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE]))
|
cg.add(var.set_warm_white_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE]))
|
||||||
|
|
||||||
|
if CONF_OFF_COLOR_TEMPERATURE in config:
|
||||||
|
if config[CONF_OFF_COLOR_TEMPERATURE] == CONF_COLD_WHITE:
|
||||||
|
cg.add(
|
||||||
|
var.set_off_color_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE])
|
||||||
|
)
|
||||||
|
elif config[CONF_OFF_COLOR_TEMPERATURE] == CONF_WARM_WHITE:
|
||||||
|
cg.add(
|
||||||
|
var.set_off_color_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE])
|
||||||
|
)
|
||||||
|
|
|
@ -165,10 +165,11 @@ class LightColorValues {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert these light color values to an RGB+CT+BR representation with the given parameters.
|
/// Convert these light color values to an RGB+CT+BR representation with the given parameters.
|
||||||
void as_rgbct(float color_temperature_cw, float color_temperature_ww, float *red, float *green, float *blue,
|
void as_rgbct(float color_temperature_cw, float color_temperature_ww, float color_temperature_off, float *red,
|
||||||
float *color_temperature, float *white_brightness, float gamma = 0) const {
|
float *green, float *blue, float *color_temperature, float *white_brightness, float gamma = 0) const {
|
||||||
this->as_rgb(red, green, blue, gamma);
|
this->as_rgb(red, green, blue, gamma);
|
||||||
this->as_ct(color_temperature_cw, color_temperature_ww, color_temperature, white_brightness, gamma);
|
this->as_ct(color_temperature_cw, color_temperature_ww, color_temperature_off, color_temperature, white_brightness,
|
||||||
|
gamma);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert these light color values to an CWWW representation with the given parameters.
|
/// Convert these light color values to an CWWW representation with the given parameters.
|
||||||
|
@ -196,16 +197,23 @@ class LightColorValues {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert these light color values to a CT+BR representation with the given parameters.
|
/// Convert these light color values to a CT+BR representation with the given parameters.
|
||||||
void as_ct(float color_temperature_cw, float color_temperature_ww, float *color_temperature, float *white_brightness,
|
void as_ct(float color_temperature_cw, float color_temperature_ww, float color_temperature_off,
|
||||||
float gamma = 0) const {
|
float *color_temperature, float *white_brightness, float gamma = 0) const {
|
||||||
const float white_level = this->color_mode_ & ColorCapability::RGB ? this->white_ : 1;
|
const float white_level = this->color_mode_ & ColorCapability::RGB ? this->white_ : 1;
|
||||||
|
float output_color_temperature = color_temperature_off;
|
||||||
|
|
||||||
if (this->color_mode_ & ColorCapability::COLOR_TEMPERATURE) {
|
if (this->color_mode_ & ColorCapability::COLOR_TEMPERATURE) {
|
||||||
*color_temperature =
|
|
||||||
(this->color_temperature_ - color_temperature_cw) / (color_temperature_ww - color_temperature_cw);
|
|
||||||
*white_brightness = gamma_correct(this->state_ * this->brightness_ * white_level, gamma);
|
*white_brightness = gamma_correct(this->state_ * this->brightness_ * white_level, gamma);
|
||||||
|
|
||||||
|
if (*white_brightness != 0.0f) {
|
||||||
|
output_color_temperature = this->color_temperature_;
|
||||||
|
}
|
||||||
} else { // Probably won't get here but put this here anyway.
|
} else { // Probably won't get here but put this here anyway.
|
||||||
*white_brightness = 0;
|
*white_brightness = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*color_temperature =
|
||||||
|
(output_color_temperature - color_temperature_cw) / (color_temperature_ww - color_temperature_cw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare this LightColorValues to rhs, return true if and only if all attributes match.
|
/// Compare this LightColorValues to rhs, return true if and only if all attributes match.
|
||||||
|
|
|
@ -203,8 +203,8 @@ void LightState::current_values_as_rgbww(float *red, float *green, float *blue,
|
||||||
void LightState::current_values_as_rgbct(float *red, float *green, float *blue, float *color_temperature,
|
void LightState::current_values_as_rgbct(float *red, float *green, float *blue, float *color_temperature,
|
||||||
float *white_brightness) {
|
float *white_brightness) {
|
||||||
auto traits = this->get_traits();
|
auto traits = this->get_traits();
|
||||||
this->current_values.as_rgbct(traits.get_min_mireds(), traits.get_max_mireds(), red, green, blue, color_temperature,
|
this->current_values.as_rgbct(traits.get_min_mireds(), traits.get_max_mireds(), traits.get_off_mireds(), red, green,
|
||||||
white_brightness, this->gamma_correct_);
|
blue, color_temperature, white_brightness, this->gamma_correct_);
|
||||||
}
|
}
|
||||||
void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness) {
|
void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness) {
|
||||||
auto traits = this->get_traits();
|
auto traits = this->get_traits();
|
||||||
|
@ -212,8 +212,8 @@ void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bo
|
||||||
}
|
}
|
||||||
void LightState::current_values_as_ct(float *color_temperature, float *white_brightness) {
|
void LightState::current_values_as_ct(float *color_temperature, float *white_brightness) {
|
||||||
auto traits = this->get_traits();
|
auto traits = this->get_traits();
|
||||||
this->current_values.as_ct(traits.get_min_mireds(), traits.get_max_mireds(), color_temperature, white_brightness,
|
this->current_values.as_ct(traits.get_min_mireds(), traits.get_max_mireds(), traits.get_off_mireds(),
|
||||||
this->gamma_correct_);
|
color_temperature, white_brightness, this->gamma_correct_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LightState::is_transformer_active() { return this->is_transformer_active_; }
|
bool LightState::is_transformer_active() { return this->is_transformer_active_; }
|
||||||
|
|
|
@ -50,11 +50,14 @@ class LightTraits {
|
||||||
void set_min_mireds(float min_mireds) { this->min_mireds_ = min_mireds; }
|
void set_min_mireds(float min_mireds) { this->min_mireds_ = min_mireds; }
|
||||||
float get_max_mireds() const { return this->max_mireds_; }
|
float get_max_mireds() const { return this->max_mireds_; }
|
||||||
void set_max_mireds(float max_mireds) { this->max_mireds_ = max_mireds; }
|
void set_max_mireds(float max_mireds) { this->max_mireds_ = max_mireds; }
|
||||||
|
float get_off_mireds() const { return this->off_mireds_; }
|
||||||
|
void set_off_mireds(float off_mireds) { this->off_mireds_ = off_mireds; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::set<ColorMode> supported_color_modes_{};
|
std::set<ColorMode> supported_color_modes_{};
|
||||||
float min_mireds_{0};
|
float min_mireds_{0};
|
||||||
float max_mireds_{0};
|
float max_mireds_{0};
|
||||||
|
float off_mireds_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace light
|
} // namespace light
|
||||||
|
|
|
@ -10,6 +10,9 @@ from esphome.const import (
|
||||||
CONF_OUTPUT_ID,
|
CONF_OUTPUT_ID,
|
||||||
CONF_COLD_WHITE_COLOR_TEMPERATURE,
|
CONF_COLD_WHITE_COLOR_TEMPERATURE,
|
||||||
CONF_WARM_WHITE_COLOR_TEMPERATURE,
|
CONF_WARM_WHITE_COLOR_TEMPERATURE,
|
||||||
|
CONF_OFF_COLOR_TEMPERATURE,
|
||||||
|
CONF_COLD_WHITE,
|
||||||
|
CONF_WARM_WHITE,
|
||||||
)
|
)
|
||||||
|
|
||||||
CODEOWNERS = ["@jesserockz"]
|
CODEOWNERS = ["@jesserockz"]
|
||||||
|
@ -30,6 +33,12 @@ CONFIG_SCHEMA = cv.All(
|
||||||
cv.Required(CONF_WHITE_BRIGHTNESS): cv.use_id(output.FloatOutput),
|
cv.Required(CONF_WHITE_BRIGHTNESS): cv.use_id(output.FloatOutput),
|
||||||
cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
|
cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
|
||||||
cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
|
cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
|
||||||
|
cv.Optional(CONF_OFF_COLOR_TEMPERATURE): cv.enum(
|
||||||
|
{
|
||||||
|
CONF_COLD_WHITE: None,
|
||||||
|
CONF_WARM_WHITE: None,
|
||||||
|
}
|
||||||
|
),
|
||||||
cv.Optional(CONF_COLOR_INTERLOCK, default=False): cv.boolean,
|
cv.Optional(CONF_COLOR_INTERLOCK, default=False): cv.boolean,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
@ -56,4 +65,14 @@ async def to_code(config):
|
||||||
cg.add(var.set_cold_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE]))
|
cg.add(var.set_cold_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE]))
|
||||||
cg.add(var.set_warm_white_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE]))
|
cg.add(var.set_warm_white_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE]))
|
||||||
|
|
||||||
|
if CONF_OFF_COLOR_TEMPERATURE in config:
|
||||||
|
if config[CONF_OFF_COLOR_TEMPERATURE] == CONF_COLD_WHITE:
|
||||||
|
cg.add(
|
||||||
|
var.set_off_color_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE])
|
||||||
|
)
|
||||||
|
elif config[CONF_OFF_COLOR_TEMPERATURE] == CONF_WARM_WHITE:
|
||||||
|
cg.add(
|
||||||
|
var.set_off_color_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE])
|
||||||
|
)
|
||||||
|
|
||||||
cg.add(var.set_color_interlock(config[CONF_COLOR_INTERLOCK]))
|
cg.add(var.set_color_interlock(config[CONF_COLOR_INTERLOCK]))
|
||||||
|
|
|
@ -19,6 +19,7 @@ class RGBCTLightOutput : public light::LightOutput {
|
||||||
|
|
||||||
void set_cold_white_temperature(float cold_white_temperature) { cold_white_temperature_ = cold_white_temperature; }
|
void set_cold_white_temperature(float cold_white_temperature) { cold_white_temperature_ = cold_white_temperature; }
|
||||||
void set_warm_white_temperature(float warm_white_temperature) { warm_white_temperature_ = warm_white_temperature; }
|
void set_warm_white_temperature(float warm_white_temperature) { warm_white_temperature_ = warm_white_temperature; }
|
||||||
|
void set_off_color_temperature(float off_color_temperature) { off_color_temperature_ = off_color_temperature; }
|
||||||
void set_color_interlock(bool color_interlock) { color_interlock_ = color_interlock; }
|
void set_color_interlock(bool color_interlock) { color_interlock_ = color_interlock; }
|
||||||
|
|
||||||
light::LightTraits get_traits() override {
|
light::LightTraits get_traits() override {
|
||||||
|
@ -29,6 +30,7 @@ class RGBCTLightOutput : public light::LightOutput {
|
||||||
traits.set_supported_color_modes({light::ColorMode::RGB_COLOR_TEMPERATURE, light::ColorMode::COLOR_TEMPERATURE});
|
traits.set_supported_color_modes({light::ColorMode::RGB_COLOR_TEMPERATURE, light::ColorMode::COLOR_TEMPERATURE});
|
||||||
traits.set_min_mireds(this->cold_white_temperature_);
|
traits.set_min_mireds(this->cold_white_temperature_);
|
||||||
traits.set_max_mireds(this->warm_white_temperature_);
|
traits.set_max_mireds(this->warm_white_temperature_);
|
||||||
|
traits.set_off_mireds(this->off_color_temperature_);
|
||||||
return traits;
|
return traits;
|
||||||
}
|
}
|
||||||
void write_state(light::LightState *state) override {
|
void write_state(light::LightState *state) override {
|
||||||
|
@ -51,6 +53,7 @@ class RGBCTLightOutput : public light::LightOutput {
|
||||||
output::FloatOutput *white_brightness_;
|
output::FloatOutput *white_brightness_;
|
||||||
float cold_white_temperature_;
|
float cold_white_temperature_;
|
||||||
float warm_white_temperature_;
|
float warm_white_temperature_;
|
||||||
|
float off_color_temperature_{0};
|
||||||
bool color_interlock_{true};
|
bool color_interlock_{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -516,6 +516,7 @@ CONF_NUM_SCANS = "num_scans"
|
||||||
CONF_NUMBER = "number"
|
CONF_NUMBER = "number"
|
||||||
CONF_NUMBER_DATAPOINT = "number_datapoint"
|
CONF_NUMBER_DATAPOINT = "number_datapoint"
|
||||||
CONF_OE_PIN = "oe_pin"
|
CONF_OE_PIN = "oe_pin"
|
||||||
|
CONF_OFF_COLOR_TEMPERATURE = "off_color_temperature"
|
||||||
CONF_OFF_MODE = "off_mode"
|
CONF_OFF_MODE = "off_mode"
|
||||||
CONF_OFF_SPEED_CYCLE = "off_speed_cycle"
|
CONF_OFF_SPEED_CYCLE = "off_speed_cycle"
|
||||||
CONF_OFFSET = "offset"
|
CONF_OFFSET = "offset"
|
||||||
|
|
Loading…
Reference in a new issue