mirror of
https://github.com/esphome/esphome.git
synced 2024-12-25 23:14:54 +01:00
RGBWW - added channel interlock for RGB vs white (#1042)
* Update light_color_values.h * Update light_color_values.h * Update light_color_values.h * Update light_color_values.h * colour relative to white value * Update light_state.cpp * Update light_state.cpp * Update light_state.cpp * Update light_state.cpp * Update light_color_values.h * Update light_state.cpp * linting * Update light_state.cpp * Update light_color_values.h * more lint * more lint * Update light_state.cpp * Update light_state.cpp * Update light_state.cpp * add optional interlock * Update test1.yaml * Update light_state.cpp * Update light_state.h * interlock * optional interlock. * interlock as trait * color interlock as trait * optional color interlock.... * optional color interlock * Update light_color_values.h * Lint checks.... * making travis happy * making sure gamma_correct fix is included * Update light_color_values.h * making travis happy * clang-format * Code tidy * Update light_color_values.h * Update light_color_values.h
This commit is contained in:
parent
33212d1abf
commit
e5d4e12457
10 changed files with 83 additions and 28 deletions
|
@ -179,22 +179,28 @@ class LightColorValues {
|
|||
}
|
||||
|
||||
/// Convert these light color values to an RGB representation and write them to red, green, blue.
|
||||
void as_rgb(float *red, float *green, float *blue, float gamma = 0) const {
|
||||
*red = gamma_correct(this->state_ * this->brightness_ * this->red_, gamma);
|
||||
*green = gamma_correct(this->state_ * this->brightness_ * this->green_, gamma);
|
||||
*blue = gamma_correct(this->state_ * this->brightness_ * this->blue_, gamma);
|
||||
void as_rgb(float *red, float *green, float *blue, float gamma = 0, bool color_interlock = false) const {
|
||||
float brightness = this->state_ * this->brightness_;
|
||||
if (color_interlock) {
|
||||
brightness = brightness * (1.0f - this->white_);
|
||||
}
|
||||
*red = gamma_correct(brightness * this->red_, gamma);
|
||||
*green = gamma_correct(brightness * this->green_, gamma);
|
||||
*blue = gamma_correct(brightness * this->blue_, gamma);
|
||||
}
|
||||
|
||||
/// Convert these light color values to an RGBW representation and write them to red, green, blue, white.
|
||||
void as_rgbw(float *red, float *green, float *blue, float *white, float gamma = 0) const {
|
||||
this->as_rgb(red, green, blue, gamma);
|
||||
void as_rgbw(float *red, float *green, float *blue, float *white, float gamma = 0,
|
||||
bool color_interlock = false) const {
|
||||
this->as_rgb(red, green, blue, gamma, color_interlock);
|
||||
*white = gamma_correct(this->state_ * this->brightness_ * this->white_, gamma);
|
||||
}
|
||||
|
||||
/// Convert these light color values to an RGBWW representation with the given parameters.
|
||||
void as_rgbww(float color_temperature_cw, float color_temperature_ww, float *red, float *green, float *blue,
|
||||
float *cold_white, float *warm_white, float gamma = 0, bool constant_brightness = false) const {
|
||||
this->as_rgb(red, green, blue, gamma);
|
||||
float *cold_white, float *warm_white, float gamma = 0, bool constant_brightness = false,
|
||||
bool color_interlock = false) const {
|
||||
this->as_rgb(red, green, blue, gamma, color_interlock);
|
||||
const float color_temp = clamp(this->color_temperature_, color_temperature_cw, color_temperature_ww);
|
||||
const float ww_fraction = (color_temp - color_temperature_cw) / (color_temperature_ww - color_temperature_cw);
|
||||
const float cw_fraction = 1.0f - ww_fraction;
|
||||
|
|
|
@ -400,26 +400,51 @@ LightColorValues LightCall::validate_() {
|
|||
this->green_ = optional<float>(1.0f);
|
||||
this->blue_ = optional<float>(1.0f);
|
||||
}
|
||||
// make white values binary aka 0.0f or 1.0f...this allows brightness to do its job
|
||||
if (traits.get_supports_color_interlock()) {
|
||||
if (*this->white_ > 0.0f) {
|
||||
this->white_ = optional<float>(1.0f);
|
||||
} else {
|
||||
this->white_ = optional<float>(0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
// White to 0% if (exclusively) setting any RGB value
|
||||
// White to 0% if (exclusively) setting any RGB value that isn't 255,255,255
|
||||
else if (this->red_.has_value() || this->green_.has_value() || this->blue_.has_value()) {
|
||||
if (!this->white_.has_value()) {
|
||||
if (*this->red_ == 1.0f && *this->green_ == 1.0f && *this->blue_ == 1.0f && traits.get_supports_rgb_white_value() &&
|
||||
traits.get_supports_color_interlock()) {
|
||||
this->white_ = optional<float>(1.0f);
|
||||
} else if (!this->white_.has_value() || !traits.get_supports_rgb_white_value()) {
|
||||
this->white_ = optional<float>(0.0f);
|
||||
}
|
||||
}
|
||||
// if changing Kelvin alone, change to white light
|
||||
else if (this->color_temperature_.has_value()) {
|
||||
if (!this->red_.has_value() && !this->green_.has_value() && !this->blue_.has_value()) {
|
||||
this->red_ = optional<float>(1.0f);
|
||||
this->green_ = optional<float>(1.0f);
|
||||
this->blue_ = optional<float>(1.0f);
|
||||
if (!traits.get_supports_color_interlock()) {
|
||||
if (!this->red_.has_value() && !this->green_.has_value() && !this->blue_.has_value()) {
|
||||
this->red_ = optional<float>(1.0f);
|
||||
this->green_ = optional<float>(1.0f);
|
||||
this->blue_ = optional<float>(1.0f);
|
||||
}
|
||||
}
|
||||
// if setting Kelvin from color (i.e. switching to white light), set White to 100%
|
||||
auto cv = this->parent_->remote_values;
|
||||
bool was_color = cv.get_red() != 1.0f || cv.get_blue() != 1.0f || cv.get_green() != 1.0f;
|
||||
bool now_white = *this->red_ == 1.0f && *this->blue_ == 1.0f && *this->green_ == 1.0f;
|
||||
if (!this->white_.has_value() && was_color && now_white) {
|
||||
this->white_ = optional<float>(1.0f);
|
||||
if (traits.get_supports_color_interlock()) {
|
||||
if (cv.get_white() < 1.0f) {
|
||||
this->white_ = optional<float>(1.0f);
|
||||
}
|
||||
|
||||
if (was_color && !this->red_.has_value() && !this->green_.has_value() && !this->blue_.has_value()) {
|
||||
this->red_ = optional<float>(1.0f);
|
||||
this->green_ = optional<float>(1.0f);
|
||||
this->blue_ = optional<float>(1.0f);
|
||||
}
|
||||
} else {
|
||||
if (!this->white_.has_value() && was_color && now_white) {
|
||||
this->white_ = optional<float>(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -704,17 +729,20 @@ void LightState::current_values_as_binary(bool *binary) { this->current_values.a
|
|||
void LightState::current_values_as_brightness(float *brightness) {
|
||||
this->current_values.as_brightness(brightness, this->gamma_correct_);
|
||||
}
|
||||
void LightState::current_values_as_rgb(float *red, float *green, float *blue) {
|
||||
this->current_values.as_rgb(red, green, blue, this->gamma_correct_);
|
||||
void LightState::current_values_as_rgb(float *red, float *green, float *blue, bool color_interlock) {
|
||||
auto traits = this->get_traits();
|
||||
this->current_values.as_rgb(red, green, blue, this->gamma_correct_, traits.get_supports_color_interlock());
|
||||
}
|
||||
void LightState::current_values_as_rgbw(float *red, float *green, float *blue, float *white) {
|
||||
this->current_values.as_rgbw(red, green, blue, white, this->gamma_correct_);
|
||||
void LightState::current_values_as_rgbw(float *red, float *green, float *blue, float *white, bool color_interlock) {
|
||||
auto traits = this->get_traits();
|
||||
this->current_values.as_rgbw(red, green, blue, white, this->gamma_correct_, traits.get_supports_color_interlock());
|
||||
}
|
||||
void LightState::current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white,
|
||||
bool constant_brightness) {
|
||||
bool constant_brightness, bool color_interlock) {
|
||||
auto traits = this->get_traits();
|
||||
this->current_values.as_rgbww(traits.get_min_mireds(), traits.get_max_mireds(), red, green, blue, cold_white,
|
||||
warm_white, this->gamma_correct_, constant_brightness);
|
||||
warm_white, this->gamma_correct_, constant_brightness,
|
||||
traits.get_supports_color_interlock());
|
||||
}
|
||||
void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness) {
|
||||
auto traits = this->get_traits();
|
||||
|
|
|
@ -266,12 +266,12 @@ class LightState : public Nameable, public Component {
|
|||
|
||||
void current_values_as_brightness(float *brightness);
|
||||
|
||||
void current_values_as_rgb(float *red, float *green, float *blue);
|
||||
void current_values_as_rgb(float *red, float *green, float *blue, bool color_interlock = false);
|
||||
|
||||
void current_values_as_rgbw(float *red, float *green, float *blue, float *white);
|
||||
void current_values_as_rgbw(float *red, float *green, float *blue, float *white, bool color_interlock = false);
|
||||
|
||||
void current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white,
|
||||
bool constant_brightness = false);
|
||||
bool constant_brightness = false, bool color_interlock = false);
|
||||
|
||||
void current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness = false);
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@ class LightTraits {
|
|||
void set_supports_color_temperature(bool supports_color_temperature) {
|
||||
this->supports_color_temperature_ = supports_color_temperature;
|
||||
}
|
||||
bool get_supports_color_interlock() const { return this->supports_color_interlock_; }
|
||||
void set_supports_color_interlock(bool supports_color_interlock) {
|
||||
this->supports_color_interlock_ = supports_color_interlock;
|
||||
}
|
||||
float get_min_mireds() const { return this->min_mireds_; }
|
||||
void set_min_mireds(float min_mireds) { this->min_mireds_ = min_mireds; }
|
||||
float get_max_mireds() const { return this->max_mireds_; }
|
||||
|
@ -32,6 +36,7 @@ class LightTraits {
|
|||
bool supports_color_temperature_{false};
|
||||
float min_mireds_{0};
|
||||
float max_mireds_{0};
|
||||
bool supports_color_interlock_{false};
|
||||
};
|
||||
|
||||
} // namespace light
|
||||
|
|
|
@ -12,6 +12,7 @@ class RGBLightOutput : public light::LightOutput {
|
|||
void set_red(output::FloatOutput *red) { red_ = red; }
|
||||
void set_green(output::FloatOutput *green) { green_ = green; }
|
||||
void set_blue(output::FloatOutput *blue) { blue_ = blue; }
|
||||
|
||||
light::LightTraits get_traits() override {
|
||||
auto traits = light::LightTraits();
|
||||
traits.set_supports_brightness(true);
|
||||
|
@ -20,7 +21,7 @@ class RGBLightOutput : public light::LightOutput {
|
|||
}
|
||||
void write_state(light::LightState *state) override {
|
||||
float red, green, blue;
|
||||
state->current_values_as_rgb(&red, &green, &blue);
|
||||
state->current_values_as_rgb(&red, &green, &blue, false);
|
||||
this->red_->set_level(red);
|
||||
this->green_->set_level(green);
|
||||
this->blue_->set_level(blue);
|
||||
|
|
|
@ -5,6 +5,7 @@ from esphome.const import CONF_BLUE, CONF_GREEN, CONF_RED, CONF_OUTPUT_ID, CONF_
|
|||
|
||||
rgbw_ns = cg.esphome_ns.namespace('rgbw')
|
||||
RGBWLightOutput = rgbw_ns.class_('RGBWLightOutput', light.LightOutput)
|
||||
CONF_COLOR_INTERLOCK = 'color_interlock'
|
||||
|
||||
CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(RGBWLightOutput),
|
||||
|
@ -12,6 +13,7 @@ CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({
|
|||
cv.Required(CONF_GREEN): cv.use_id(output.FloatOutput),
|
||||
cv.Required(CONF_BLUE): cv.use_id(output.FloatOutput),
|
||||
cv.Required(CONF_WHITE): cv.use_id(output.FloatOutput),
|
||||
cv.Optional(CONF_COLOR_INTERLOCK, default=False): cv.boolean,
|
||||
})
|
||||
|
||||
|
||||
|
@ -27,3 +29,4 @@ def to_code(config):
|
|||
cg.add(var.set_blue(blue))
|
||||
white = yield cg.get_variable(config[CONF_WHITE])
|
||||
cg.add(var.set_white(white))
|
||||
cg.add(var.set_color_interlock(config[CONF_COLOR_INTERLOCK]))
|
||||
|
|
|
@ -13,16 +13,18 @@ class RGBWLightOutput : public light::LightOutput {
|
|||
void set_green(output::FloatOutput *green) { green_ = green; }
|
||||
void set_blue(output::FloatOutput *blue) { blue_ = blue; }
|
||||
void set_white(output::FloatOutput *white) { white_ = white; }
|
||||
void set_color_interlock(bool color_interlock) { color_interlock_ = color_interlock; }
|
||||
light::LightTraits get_traits() override {
|
||||
auto traits = light::LightTraits();
|
||||
traits.set_supports_brightness(true);
|
||||
traits.set_supports_color_interlock(this->color_interlock_);
|
||||
traits.set_supports_rgb(true);
|
||||
traits.set_supports_rgb_white_value(true);
|
||||
return traits;
|
||||
}
|
||||
void write_state(light::LightState *state) override {
|
||||
float red, green, blue, white;
|
||||
state->current_values_as_rgbw(&red, &green, &blue, &white);
|
||||
state->current_values_as_rgbw(&red, &green, &blue, &white, this->color_interlock_);
|
||||
this->red_->set_level(red);
|
||||
this->green_->set_level(green);
|
||||
this->blue_->set_level(blue);
|
||||
|
@ -34,6 +36,7 @@ class RGBWLightOutput : public light::LightOutput {
|
|||
output::FloatOutput *green_;
|
||||
output::FloatOutput *blue_;
|
||||
output::FloatOutput *white_;
|
||||
bool color_interlock_{false};
|
||||
};
|
||||
|
||||
} // namespace rgbw
|
||||
|
|
|
@ -9,6 +9,7 @@ rgbww_ns = cg.esphome_ns.namespace('rgbww')
|
|||
RGBWWLightOutput = rgbww_ns.class_('RGBWWLightOutput', light.LightOutput)
|
||||
|
||||
CONF_CONSTANT_BRIGHTNESS = 'constant_brightness'
|
||||
CONF_COLOR_INTERLOCK = 'color_interlock'
|
||||
|
||||
CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(RGBWWLightOutput),
|
||||
|
@ -20,6 +21,7 @@ CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({
|
|||
cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
|
||||
cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
|
||||
cv.Optional(CONF_CONSTANT_BRIGHTNESS, default=False): cv.boolean,
|
||||
cv.Optional(CONF_COLOR_INTERLOCK, default=False): cv.boolean,
|
||||
})
|
||||
|
||||
|
||||
|
@ -42,3 +44,4 @@ def to_code(config):
|
|||
cg.add(var.set_warm_white(wwhite))
|
||||
cg.add(var.set_warm_white_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE]))
|
||||
cg.add(var.set_constant_brightness(config[CONF_CONSTANT_BRIGHTNESS]))
|
||||
cg.add(var.set_color_interlock(config[CONF_COLOR_INTERLOCK]))
|
||||
|
|
|
@ -17,19 +17,22 @@ class RGBWWLightOutput : public light::LightOutput {
|
|||
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_constant_brightness(bool constant_brightness) { constant_brightness_ = constant_brightness; }
|
||||
void set_color_interlock(bool color_interlock) { color_interlock_ = color_interlock; }
|
||||
light::LightTraits get_traits() override {
|
||||
auto traits = light::LightTraits();
|
||||
traits.set_supports_brightness(true);
|
||||
traits.set_supports_rgb(true);
|
||||
traits.set_supports_rgb_white_value(true);
|
||||
traits.set_supports_color_temperature(true);
|
||||
traits.set_supports_color_interlock(this->color_interlock_);
|
||||
traits.set_min_mireds(this->cold_white_temperature_);
|
||||
traits.set_max_mireds(this->warm_white_temperature_);
|
||||
return traits;
|
||||
}
|
||||
void write_state(light::LightState *state) override {
|
||||
float red, green, blue, cwhite, wwhite;
|
||||
state->current_values_as_rgbww(&red, &green, &blue, &cwhite, &wwhite, this->constant_brightness_);
|
||||
state->current_values_as_rgbww(&red, &green, &blue, &cwhite, &wwhite, this->constant_brightness_,
|
||||
this->color_interlock_);
|
||||
this->red_->set_level(red);
|
||||
this->green_->set_level(green);
|
||||
this->blue_->set_level(blue);
|
||||
|
@ -46,6 +49,7 @@ class RGBWWLightOutput : public light::LightOutput {
|
|||
float cold_white_temperature_;
|
||||
float warm_white_temperature_;
|
||||
bool constant_brightness_;
|
||||
bool color_interlock_{false};
|
||||
};
|
||||
|
||||
} // namespace rgbww
|
||||
|
|
|
@ -1114,6 +1114,7 @@ light:
|
|||
green: pca_4
|
||||
blue: pca_5
|
||||
white: pca_6
|
||||
color_interlock: true
|
||||
- platform: rgbww
|
||||
name: "Living Room Lights 2"
|
||||
red: pca_3
|
||||
|
@ -1123,6 +1124,7 @@ light:
|
|||
warm_white: pca_6
|
||||
cold_white_color_temperature: 153 mireds
|
||||
warm_white_color_temperature: 500 mireds
|
||||
color_interlock: true
|
||||
- platform: cwww
|
||||
name: "Living Room Lights 2"
|
||||
cold_white: pca_6
|
||||
|
|
Loading…
Reference in a new issue