Add rgbct and color_temperature light platforms (#2138)

Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
This commit is contained in:
Jesse Hills 2021-08-10 21:28:56 +12:00 committed by GitHub
parent 854f4a8896
commit d258e06fd7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 254 additions and 4 deletions

View file

@ -29,6 +29,7 @@ esphome/components/canbus/* @danielschramm @mvturnho
esphome/components/captive_portal/* @OttoWinter esphome/components/captive_portal/* @OttoWinter
esphome/components/climate/* @esphome/core esphome/components/climate/* @esphome/core
esphome/components/climate_ir/* @glmnet esphome/components/climate_ir/* @glmnet
esphome/components/color_temperature/* @jesserockz
esphome/components/coolix/* @glmnet esphome/components/coolix/* @glmnet
esphome/components/cover/* @esphome/core esphome/components/cover/* @esphome/core
esphome/components/cs5460a/* @balrog-kun esphome/components/cs5460a/* @balrog-kun
@ -98,6 +99,7 @@ esphome/components/rc522_i2c/* @glmnet
esphome/components/rc522_spi/* @glmnet esphome/components/rc522_spi/* @glmnet
esphome/components/restart/* @esphome/core esphome/components/restart/* @esphome/core
esphome/components/rf_bridge/* @jesserockz esphome/components/rf_bridge/* @jesserockz
esphome/components/rgbct/* @jesserockz
esphome/components/rtttl/* @glmnet esphome/components/rtttl/* @glmnet
esphome/components/script/* @esphome/core esphome/components/script/* @esphome/core
esphome/components/sdm_meter/* @jesserockz @polyfaces esphome/components/sdm_meter/* @jesserockz @polyfaces

View file

@ -0,0 +1,38 @@
#pragma once
#include "esphome/components/light/light_output.h"
#include "esphome/components/output/float_output.h"
#include "esphome/core/component.h"
namespace esphome {
namespace color_temperature {
class CTLightOutput : public light::LightOutput {
public:
void set_color_temperature(output::FloatOutput *color_temperature) { color_temperature_ = color_temperature; }
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_warm_white_temperature(float warm_white_temperature) { warm_white_temperature_ = warm_white_temperature; }
light::LightTraits get_traits() override {
auto traits = light::LightTraits();
traits.set_supported_color_modes({light::ColorMode::COLOR_TEMPERATURE});
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 color_temperature, brightness;
state->current_values_as_ct(&color_temperature, &brightness);
this->color_temperature_->set_level(color_temperature);
this->brightness_->set_level(brightness);
}
protected:
output::FloatOutput *color_temperature_;
output::FloatOutput *brightness_;
float cold_white_temperature_;
float warm_white_temperature_;
};
} // namespace color_temperature
} // namespace esphome

View file

@ -0,0 +1,42 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import light, output
from esphome.const import (
CONF_BRIGHTNESS,
CONF_COLOR_TEMPERATURE,
CONF_OUTPUT_ID,
CONF_COLD_WHITE_COLOR_TEMPERATURE,
CONF_WARM_WHITE_COLOR_TEMPERATURE,
)
CODEOWNERS = ["@jesserockz"]
color_temperature_ns = cg.esphome_ns.namespace("color_temperature")
CTLightOutput = color_temperature_ns.class_("CTLightOutput", light.LightOutput)
CONFIG_SCHEMA = cv.All(
light.RGB_LIGHT_SCHEMA.extend(
{
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(CTLightOutput),
cv.Required(CONF_COLOR_TEMPERATURE): 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_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
}
),
light.validate_color_temperature_channels,
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
await light.register_light(var, config)
color_temperature = await cg.get_variable(config[CONF_COLOR_TEMPERATURE])
cg.add(var.set_color_temperature(color_temperature))
brightness = await cg.get_variable(config[CONF_BRIGHTNESS])
cg.add(var.set_brightness(brightness))
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]))

View file

@ -2,6 +2,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import light, output from esphome.components import light, output
from esphome.const import ( from esphome.const import (
CONF_CONSTANT_BRIGHTNESS,
CONF_OUTPUT_ID, CONF_OUTPUT_ID,
CONF_COLD_WHITE, CONF_COLD_WHITE,
CONF_WARM_WHITE, CONF_WARM_WHITE,
@ -12,8 +13,6 @@ from esphome.const import (
cwww_ns = cg.esphome_ns.namespace("cwww") cwww_ns = cg.esphome_ns.namespace("cwww")
CWWWLightOutput = cwww_ns.class_("CWWWLightOutput", light.LightOutput) CWWWLightOutput = cwww_ns.class_("CWWWLightOutput", light.LightOutput)
CONF_CONSTANT_BRIGHTNESS = "constant_brightness"
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(
light.RGB_LIGHT_SCHEMA.extend( light.RGB_LIGHT_SCHEMA.extend(
{ {

View file

@ -163,6 +163,13 @@ class LightColorValues {
this->as_cwww(cold_white, warm_white, gamma, constant_brightness); this->as_cwww(cold_white, warm_white, gamma, constant_brightness);
} }
/// 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,
float *color_temperature, float *white_brightness, float gamma = 0) const {
this->as_rgb(red, green, blue, gamma);
this->as_ct(color_temperature_cw, color_temperature_ww, 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.
void as_cwww(float *cold_white, float *warm_white, float gamma = 0, bool constant_brightness = false) const { void as_cwww(float *cold_white, float *warm_white, float gamma = 0, bool constant_brightness = false) const {
if (this->color_mode_ & ColorCapability::COLD_WARM_WHITE) { if (this->color_mode_ & ColorCapability::COLD_WARM_WHITE) {
@ -187,6 +194,19 @@ class LightColorValues {
} }
} }
/// 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,
float gamma = 0) const {
const float white_level = this->color_mode_ & ColorCapability::RGB ? this->white_ : 1;
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);
} else { // Probably wont get here but put this here anyway.
*white_brightness = 0;
}
}
/// 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.
bool operator==(const LightColorValues &rhs) const { bool operator==(const LightColorValues &rhs) const {
return color_mode_ == rhs.color_mode_ && state_ == rhs.state_ && brightness_ == rhs.brightness_ && return color_mode_ == rhs.color_mode_ && state_ == rhs.state_ && brightness_ == rhs.brightness_ &&

View file

@ -175,13 +175,23 @@ void LightState::current_values_as_rgbw(float *red, float *green, float *blue, f
} }
void LightState::current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white, void LightState::current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white,
bool constant_brightness) { bool constant_brightness) {
auto traits = this->get_traits();
this->current_values.as_rgbww(red, green, blue, cold_white, warm_white, this->gamma_correct_, constant_brightness); this->current_values.as_rgbww(red, green, blue, cold_white, warm_white, this->gamma_correct_, constant_brightness);
} }
void LightState::current_values_as_rgbct(float *red, float *green, float *blue, float *color_temperature,
float *white_brightness) {
auto traits = this->get_traits();
this->current_values.as_rgbct(traits.get_min_mireds(), traits.get_max_mireds(), red, green, 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();
this->current_values.as_cwww(cold_white, warm_white, this->gamma_correct_, constant_brightness); this->current_values.as_cwww(cold_white, warm_white, this->gamma_correct_, constant_brightness);
} }
void LightState::current_values_as_ct(float *color_temperature, float *white_brightness) {
auto traits = this->get_traits();
this->current_values.as_ct(traits.get_min_mireds(), traits.get_max_mireds(), color_temperature, white_brightness,
this->gamma_correct_);
}
void LightState::start_effect_(uint32_t effect_index) { void LightState::start_effect_(uint32_t effect_index) {
this->stop_effect_(); this->stop_effect_();

View file

@ -128,8 +128,13 @@ class LightState : public Nameable, public Component {
void current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white, 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);
void current_values_as_rgbct(float *red, float *green, float *blue, float *color_temperature,
float *white_brightness);
void current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness = false); void current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness = false);
void current_values_as_ct(float *color_temperature, float *white_brightness);
protected: protected:
friend LightOutput; friend LightOutput;
friend LightCall; friend LightCall;

View file

View file

@ -0,0 +1,59 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import light, output
from esphome.const import (
CONF_BLUE,
CONF_COLOR_TEMPERATURE,
CONF_GREEN,
CONF_RED,
CONF_OUTPUT_ID,
CONF_COLD_WHITE_COLOR_TEMPERATURE,
CONF_WARM_WHITE_COLOR_TEMPERATURE,
)
CODEOWNERS = ["@jesserockz"]
rgbct_ns = cg.esphome_ns.namespace("rgbct")
RGBCTLightOutput = rgbct_ns.class_("RGBCTLightOutput", light.LightOutput)
CONF_COLOR_INTERLOCK = "color_interlock"
CONF_WHITE_BRIGHTNESS = "white_brightness"
CONFIG_SCHEMA = cv.All(
light.RGB_LIGHT_SCHEMA.extend(
{
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(RGBCTLightOutput),
cv.Required(CONF_RED): cv.use_id(output.FloatOutput),
cv.Required(CONF_GREEN): cv.use_id(output.FloatOutput),
cv.Required(CONF_BLUE): cv.use_id(output.FloatOutput),
cv.Required(CONF_COLOR_TEMPERATURE): 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_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
cv.Optional(CONF_COLOR_INTERLOCK, default=False): cv.boolean,
}
),
light.validate_color_temperature_channels,
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
await light.register_light(var, config)
red = await cg.get_variable(config[CONF_RED])
cg.add(var.set_red(red))
green = await cg.get_variable(config[CONF_GREEN])
cg.add(var.set_green(green))
blue = await cg.get_variable(config[CONF_BLUE])
cg.add(var.set_blue(blue))
color_temp = await cg.get_variable(config[CONF_COLOR_TEMPERATURE])
cg.add(var.set_color_temperature(color_temp))
white_brightness = await cg.get_variable(config[CONF_WHITE_BRIGHTNESS])
cg.add(var.set_white_brightness(white_brightness))
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_color_interlock(config[CONF_COLOR_INTERLOCK]))

View file

@ -0,0 +1,58 @@
#pragma once
#include "esphome/components/light/color_mode.h"
#include "esphome/components/light/light_output.h"
#include "esphome/components/output/float_output.h"
#include "esphome/core/component.h"
namespace esphome {
namespace rgbct {
class RGBCTLightOutput : public light::LightOutput {
public:
void set_red(output::FloatOutput *red) { red_ = red; }
void set_green(output::FloatOutput *green) { green_ = green; }
void set_blue(output::FloatOutput *blue) { blue_ = blue; }
void set_color_temperature(output::FloatOutput *color_temperature) { color_temperature_ = color_temperature; }
void set_white_brightness(output::FloatOutput *white_brightness) { white_brightness_ = white_brightness; }
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_color_interlock(bool color_interlock) { color_interlock_ = color_interlock; }
light::LightTraits get_traits() override {
auto traits = light::LightTraits();
if (this->color_interlock_)
traits.set_supported_color_modes({light::ColorMode::RGB, light::ColorMode::COLOR_TEMPERATURE});
else
traits.set_supported_color_modes({light::ColorMode::RGB_COLOR_TEMPERATURE, light::ColorMode::COLOR_TEMPERATURE});
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, color_temperature, white_brightness;
state->current_values_as_rgbct(&red, &green, &blue, &color_temperature, &white_brightness);
this->red_->set_level(red);
this->green_->set_level(green);
this->blue_->set_level(blue);
this->color_temperature_->set_level(color_temperature);
this->white_brightness_->set_level(white_brightness);
}
protected:
output::FloatOutput *red_;
output::FloatOutput *green_;
output::FloatOutput *blue_;
output::FloatOutput *color_temperature_;
output::FloatOutput *white_brightness_;
float cold_white_temperature_;
float warm_white_temperature_;
bool color_interlock_{true};
};
} // namespace rgbct
} // namespace esphome

View file

@ -3,6 +3,7 @@ import esphome.config_validation as cv
from esphome.components import light, output from esphome.components import light, output
from esphome.const import ( from esphome.const import (
CONF_BLUE, CONF_BLUE,
CONF_CONSTANT_BRIGHTNESS,
CONF_GREEN, CONF_GREEN,
CONF_RED, CONF_RED,
CONF_OUTPUT_ID, CONF_OUTPUT_ID,
@ -15,7 +16,6 @@ from esphome.const import (
rgbww_ns = cg.esphome_ns.namespace("rgbww") rgbww_ns = cg.esphome_ns.namespace("rgbww")
RGBWWLightOutput = rgbww_ns.class_("RGBWWLightOutput", light.LightOutput) RGBWWLightOutput = rgbww_ns.class_("RGBWWLightOutput", light.LightOutput)
CONF_CONSTANT_BRIGHTNESS = "constant_brightness"
CONF_COLOR_INTERLOCK = "color_interlock" CONF_COLOR_INTERLOCK = "color_interlock"
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(

View file

@ -134,6 +134,7 @@ CONF_COMPONENTS = "components"
CONF_CONDITION = "condition" CONF_CONDITION = "condition"
CONF_CONDITION_ID = "condition_id" CONF_CONDITION_ID = "condition_id"
CONF_CONDUCTIVITY = "conductivity" CONF_CONDUCTIVITY = "conductivity"
CONF_CONSTANT_BRIGHTNESS = "constant_brightness"
CONF_CONTRAST = "contrast" CONF_CONTRAST = "contrast"
CONF_COOL_ACTION = "cool_action" CONF_COOL_ACTION = "cool_action"
CONF_COOL_DEADBAND = "cool_deadband" CONF_COOL_DEADBAND = "cool_deadband"

View file

@ -1429,6 +1429,16 @@ light:
cold_white_color_temperature: 153 mireds cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds warm_white_color_temperature: 500 mireds
color_interlock: true color_interlock: true
- platform: rgbct
name: 'Living Room Lights 2'
red: pca_3
green: pca_4
blue: pca_5
color_temperature: pca_6
white_brightness: pca_6
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: cwww - platform: cwww
name: 'Living Room Lights 2' name: 'Living Room Lights 2'
cold_white: pca_6 cold_white: pca_6
@ -1436,6 +1446,12 @@ light:
cold_white_color_temperature: 153 mireds cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds warm_white_color_temperature: 500 mireds
constant_brightness: true constant_brightness: true
- platform: color_temperature
name: 'Living Room Lights 2'
color_temperature: pca_6
brightness: pca_6
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
- platform: fastled_clockless - platform: fastled_clockless
id: addr1 id: addr1
chipset: WS2811 chipset: WS2811