Skip to content

Instantly share code, notes, and snippets.

@triphoppingman
Created November 22, 2019 05:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save triphoppingman/76153ddf58072b10e229e9147b2bdf72 to your computer and use it in GitHub Desktop.
Save triphoppingman/76153ddf58072b10e229e9147b2bdf72 to your computer and use it in GitHub Desktop.
ESPHOME custom light that provides color temperature support to RGBW lights. This differs from the original (see link in the code) by mapping the RGBW from the
#include "esphome.h"
// Constants
const float maxMired = 500;
const float minMired = 153;
const float scale1 = 1.25f;
const float red_offset = 0.4f;
const float green_offset = 0.8f;
/**
* Map a RGBW Light into a tunable color / RGB Light
*
* Bruce McDonald, Frank Evers (I think)
*
* derived from:
* https://gist.github.com/madjam002/31cc88640efa370630fed6914fa4eb7f
*/
class ColorTempRGBWLight : public Component, public LightOutput {
public:
ColorTempRGBWLight(
FloatOutput *red,
FloatOutput *green,
FloatOutput *blue,
FloatOutput *white
) {
red_ = red;
green_ = green;
blue_ = blue;
white_ = white;
// Create initial state
colorTemp_ = -1.0f;
brightness_ = -1.0f;
rgbChanged_ = false;
// default scaling
cr = 1;
br = 0;
cg = 0.6;
bg = 0;
cb = -1.5;
bb = 0.5;
cw = -0.7;
bw = 1;
}
/**
* Constructor with scaling provided.
*/
ColorTempRGBWLight(
FloatOutput *red,
FloatOutput *green,
FloatOutput *blue,
FloatOutput *white,
float _br,
float _cr,
float _bg,
float _cg,
float _bb,
float _cb,
float _bw,
float _cw
) {
red_ = red;
green_ = green;
blue_ = blue;
white_ = white;
// Create initial state
colorTemp_ = -1.0f;
brightness_ = -1.0f;
rgbChanged_ = false;
// Configured scaling
cr = _cr;
br = _br;
cg = _cg;
bg = _bg;
cb = _cb;
bb = _bb;
cw = _cw;
bw = _bw;
}
/**
* Get the traits for this light
*/
LightTraits get_traits() override {
auto traits = LightTraits();
traits.set_supports_brightness(true);
traits.set_supports_rgb(true);
traits.set_supports_rgb_white_value(false);
traits.set_supports_color_temperature(true);
traits.set_min_mireds(minMired); // home assistant minimum 153
traits.set_max_mireds(maxMired); // home assistant maximum 500
return traits;
}
/**
* Write the state to this light
*/
void write_state(LightState *state) override {
float colorTemp, brightness;
state->current_values_as_brightness(&brightness);
colorTemp = state->current_values.get_color_temperature();
// If the color temp changed or the color temp is unchanged but the brightness is changed then process that.
if(colorTemp != colorTemp_ || (!rgbChanged_ && brightness != brightness_)) {
// Normalize the colorTemp
float xaxis = (colorTemp - minMired) / (maxMired - minMired); // Varies from 0 to 1 as it moves from MIN to MAX
// Place the rgb values on three lines
float red = std::min(std::max((cr * xaxis + br) * brightness,0.0f), 1.0f);
float green = std::min(std::max((cg * xaxis + bg) * brightness,0.0f), 1.0f);
float blue = std::min(std::max((cb * xaxis + bb) * brightness,0.0f), 1.0f);
float white = std::min(std::max((cw * xaxis + bw) * brightness,0.0f), 1.0f);
this->red_->set_level(red);
this->green_->set_level(green);
this->blue_->set_level(blue);
this->white_->set_level(white);
// ESP_LOGD("custom",
// "Outputs: Xaxis: %f, Red %f, Green %f Blue %f White %f",
// xaxis, xaxis * brightness, xaxis/2.5f * brightness, std::max(-xaxis * 2 + 2, 0.0f) * brightness, (-xaxis * 0.6 + 1) * brightness);
// Store this
colorTemp_ = colorTemp;
rgbChanged_ = false;
} else {
float red, green, blue, cwhite, wwhite;
state->current_values_as_rgbww(&red, &green, &blue, &cwhite, &wwhite);
this->red_->set_level(red);
this->green_->set_level(green);
this->blue_->set_level(blue);
this->white_->set_level(0);
// remember a color change
rgbChanged_ = true;
}
brightness_ = brightness;
}
protected:
FloatOutput *red_;
FloatOutput *green_;
FloatOutput *blue_;
FloatOutput *white_;
float colorTemp_;
float brightness_;
bool rgbChanged_;
// red intercept and scale
float br;
float cr;
// green intercept and scale
float bg;
float cg;
// blue intercept and scale
float bb;
float cb;
// white intercept and scale
float bw;
float cw;
};
@triphoppingman
Copy link
Author

The original author is Jamie Greeff - https://gist.github.com/madjam002

@vandarin
Copy link

vandarin commented May 4, 2020

Thanks for this! I added another check around setting RGB values -- one of my automations would turn off the White channel when the light was already on and set to white.

https://gist.github.com/vandarin/5782958e9eca16b3caf4c7742e8d9d24

@lmcd
Copy link

lmcd commented Nov 5, 2023

Is there any reason why this hasn't been submitted as a PR for ESPHome?

@triphoppingman
Copy link
Author

triphoppingman commented Nov 6, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment