-
-
Save vandarin/5782958e9eca16b3caf4c7742e8d9d24 to your computer and use it in GitHub Desktop.
#include "esphome.h" | |
enum mode {RGB, White}; | |
// Constants | |
const float maxMired = 500; | |
const float minMired = 153; | |
/** | |
* Map a RGBW Light into a tunable color / RGB Light | |
* | |
* Lane Roberts | |
* | |
* derived from: | |
* https://gist.github.com/madjam002/31cc88640efa370630fed6914fa4eb7f | |
* https://gist.github.com/triphoppingman/76153ddf58072b10e229e9147b2bdf72 | |
*/ | |
class CustomRGBWLight : public Component, public LightOutput { | |
public: | |
CustomRGBWLight( | |
FloatOutput *red, | |
FloatOutput *green, | |
FloatOutput *blue, | |
FloatOutput *white | |
) { | |
red_output = red; | |
green_output = green; | |
blue_output = blue; | |
white_output = white; | |
// Create initial state | |
colorTemp_ = -1.0f; | |
brightness_ = -1.0f; | |
mode_ = White; | |
// 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. | |
*/ | |
CustomRGBWLight( | |
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_output = red; | |
green_output = green; | |
blue_output = blue; | |
white_output = white; | |
// Create initial state | |
colorTemp_ = -1.0f; | |
brightness_ = -1.0f; | |
mode_ = White; | |
// 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(); | |
float red, green, blue, cwhite, wwhite; | |
state->current_values_as_rgbww(&red, &green, &blue, &cwhite, &wwhite); | |
// Switch modes if rgb values have been sent or if color temp value has been sent | |
if (colorTemp != colorTemp_) | |
{ | |
mode_ = White; | |
} | |
else if (red != oldRed || green != oldGreen || blue != oldBlue) | |
{ | |
mode_ = RGB; | |
} | |
if (brightness != brightness_ && (cwhite > 0.0f || wwhite > 0.0f)) | |
{ | |
mode_ = White; | |
} | |
// ESP_LOGD("custom", " CWhite: %.2f | WWhite: %.2f ", cwhite, wwhite); | |
if(mode_ == White) { | |
// 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_output->set_level(red); | |
this->green_output->set_level(green); | |
this->blue_output->set_level(blue); | |
this->white_output->set_level(white); | |
// Store this | |
colorTemp_ = colorTemp; | |
} else { | |
this->red_output->set_level(red); | |
this->green_output->set_level(green); | |
this->blue_output->set_level(blue); | |
this->white_output->set_level(0); | |
} | |
this->oldRed = red; | |
this->oldGreen = green; | |
this->oldBlue = blue; | |
brightness_ = brightness; | |
} | |
protected: | |
FloatOutput *red_output; | |
FloatOutput *green_output; | |
FloatOutput *blue_output; | |
FloatOutput *white_output; | |
float oldRed; | |
float oldGreen; | |
float oldBlue; | |
float colorTemp_; | |
float brightness_; | |
mode mode_; | |
// 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; | |
}; |
I'm assuming you're talking about this scenario:
- The light is set to an RGB color
- The light is turned off
- Home assistant sends a white+temperature state to the bulb
- The bulb comes on at RGB white, but the white channel stays at 0.
No, I know why it's doing it, but I haven't reasoned out the logic to fix it yet. Sending XY states and HA profiles don't seem to be doing what I think they should either.
I think I got it. The logic could be cleaned up a little bit, but sending a state with color_temperature always activates the white channel, and sending brightness does the right thing in both White and RGB modes.
I have successfully integrated the solution from this guide. Unfortunately the Brightnes slider and Colortemparatur slider is not linear. That's why I tried this solution, unfortunately without success.
I saved the code from above in a file called ColorTempRGBWLight.h
. This file is then saved in the following directory: /config/esphome/
.
Then I adjusted my "light.yaml" as follows (as it is described here):
esphome:
name: buro_03_esph
platform: ESP8266
board: esp01_1m
includes:
- ColorTempRGBWLight.h
wifi:
*******
*******
captive_portal:
logger:
api:
ota:
my9231:
data_pin: GPIO13
clock_pin: GPIO15
num_channels: 4
num_chips: 1
bit_depth: 8
output:
- platform: my9231
id: output_red
channel: 3
- platform: my9231
id: output_green
channel: 2
- platform: my9231
id: output_blue
channel: 1
- platform: my9231
id: output_white
channel: 0
light:
- platform: custom
lambda: |-
auto light_out = new FrankeverCustomLight(id(output_red), id(output_green), id(output_blue), id(output_white));
App.register_component(light_out);
return {light_out};
lights:
- name: buro_03_esph
default_transition_length: 1.5s
restore_mode: ALWAYS_OFF # because powercut could then cause all lights to turn on
effects:
- random:
- strobe:
- flicker:
When trying to compile the light.yaml, an error message appears. I think I did something completely wrong. Maybe in the lambda section (i just copy past from here) . Can someone help me (I'm not a programmer)? Thanks a lot
This is shown during i try to compile:
INFO Reading configuration /config/esphome/buro_01_esph.yaml...
INFO Generating C++ source...
INFO Compiling app...
INFO Running: platformio run -d /config/esphome/buro_01_esph
Processing buro_01_esph (board: esp01_1m; framework: arduino; platform: [email protected])
--------------------------------------------------------------------------------
HARDWARE: ESP8266 80MHz, 80KB RAM, 1MB Flash
PACKAGES:
- framework-arduinoespressif8266 2.20502.0 (2.5.2)
- tool-esptool 1.413.0 (4.13)
- tool-esptoolpy 1.20600.0 (2.6.0)
- toolchain-xtensa 1.40802.2 (4.8.2)
Dependency Graph
|-- <ESPAsyncTCP-esphome> 1.2.2
| |-- <ESP8266WiFi> 1.0
|-- <ESP8266WiFi> 1.0
|-- <ESP8266mDNS> 1.2
| |-- <ESP8266WiFi> 1.0
|-- <ESPAsyncWebServer-esphome> 1.2.6
| |-- <ESPAsyncTCP-esphome> 1.2.2
| | |-- <ESP8266WiFi> 1.0
| |-- <Hash> 1.0
| |-- <ESP8266WiFi> 1.0
|-- <DNSServer> 1.1.1
| |-- <ESP8266WiFi> 1.0
Compiling /data/buro_01_esph/.pioenvs/buro_01_esph/src/main.cpp.o
src/main.cpp: In lambda function:
src/main.cpp:215:28: error: expected type-specifier before 'FrankeverCustomLight'
auto light_out = new FrankeverCustomLight(output_red, output_green, output_blue, output_white);
^
src/main.cpp:217:24: error: could not convert '{light_out}' from '<brace-enclosed initializer list>' to 'std::vector<esphome::light::LightOutput*>'
return {light_out};
^
src/main.cpp:218:3: warning: control reaches end of non-void function [-Wreturn-type]
});
^
*** [/data/buro_01_esph/.pioenvs/buro_01_esph/src/main.cpp.o] Error 1
========================= [FAILED] Took 19.90 seconds =========================
Thanks a lot for sharing and answer quickly. In my light.yaml file in the lambda section, i found a mistake (changed from new FrankeverCustomLight
to new ColorTempRGBWLight
. But the error are similar:
Compiling /data/buro_01_esph/.pioenvs/buro_01_esph/src/main.cpp.o
src/main.cpp: In lambda function:
src/main.cpp:215:28: error: expected type-specifier before 'ColorTempRGBWLight'
auto light_out = new ColorTempRGBWLight(output_red, output_green, output_blue, output_white);
^
src/main.cpp:217:24: error: could not convert '{light_out}' from '<brace-enclosed initializer list>' to 'std::vector<esphome::light::LightOutput*>'
return {light_out};
^
src/main.cpp:218:3: warning: control reaches end of non-void function [-Wreturn-type]
});
^
*** [/data/buro_01_esph/.pioenvs/buro_01_esph/src/main.cpp.o] Error 1
========================= [FAILED] Took 20.21 seconds =========================
Current version: 1.14.5 (on hassio)
I think you have a mismatch between the filename and the class name. The file is named ColorTempRGBWLight.h (use this in the include: block), but if you copied from this gist, the class name that you should use in the lambda is CustomRGBWLight.
auto light_out = new CustomRGBWLight(id(output_red), id(output_green), id(output_blue), id(output_white));
Year - now its compile succsessfully
Thanks a lot vandarin
Also thanks to tripphopingman 👍
I think you have a mismatch between the filename and the class name. The file is named ColorTempRGBWLight.h (use this in the include: block), but if you copied from this gist, the class name that you should use in the lambda is CustomRGBWLight.
auto light_out = new CustomRGBWLight(id(output_red), id(output_green), id(output_blue), id(output_white));
FYI to anyone that stumbles across this, it doesn't work in the current version of esphome.
`
`
INFO Reading configuration /config/right-desk-lamp.yaml...
INFO Generating C++ source...
INFO Compiling app...
Processing right-desk-lamp (board: esp01_1m; framework: arduino; platform: platformio/espressif8266 @ 3.2.0)
HARDWARE: ESP8266 80MHz, 80KB RAM, 1MB Flash
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
Dependency Graph
|-- 1.2.3
|-- 2.1.0
| |-- 1.2.3
| |-- 1.0
| |-- 1.0
|-- 1.1.1
|-- 1.0
|-- 1.2
Compiling .pioenvs/right-desk-lamp/src/main.cpp.o
Archiving .pioenvs/right-desk-lamp/libc74/libESPAsyncWebServer-esphome.a
Archiving .pioenvs/right-desk-lamp/libfb2/libESP8266mDNS.a
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/FSnoop.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/FunctionalInterrupt.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/HardwareSerial.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/IPAddress.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/LwipDhcpServer-NonOS.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/LwipDhcpServer.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/LwipIntf.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/LwipIntfCB.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/MD5Builder.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/Print.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/Schedule.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/StackThunk.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/Stream.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/StreamSend.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/Tone.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/TypeConversion.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/Updater.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/WMath.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/WString.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/abi.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/aes_unwrap.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/base64.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/cbuf.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/cont.S.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/cont_util.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_app_entry_noextra4k.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_eboot_command.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_features.cpp.o
In file included from src/main.cpp:38:
src/ColorTempRGBWLight.h: In member function 'virtual esphome::light::LightTraits CustomRGBWLight::get_traits()':
src/ColorTempRGBWLight.h:92:12: error: 'class esphome::light::LightTraits' has no member named 'set_supports_brightness'; did you mean 'get_supports_brightness'?
92 | traits.set_supports_brightness(true);
| ^~~~~~~~~~~~~~~~~~~~~~~
| get_supports_brightness
src/ColorTempRGBWLight.h:93:12: error: 'class esphome::light::LightTraits' has no member named 'set_supports_rgb'; did you mean 'get_supports_rgb'?
93 | traits.set_supports_rgb(true);
| ^~~~~~~~~~~~~~~~
| get_supports_rgb
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_flash_quirks.cpp.o
src/ColorTempRGBWLight.h:94:12: error: 'class esphome::light::LightTraits' has no member named 'set_supports_rgb_white_value'; did you mean 'get_supports_rgb_white_value'?
94 | traits.set_supports_rgb_white_value(false);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
| get_supports_rgb_white_value
src/ColorTempRGBWLight.h:95:12: error: 'class esphome::light::LightTraits' has no member named 'set_supports_color_temperature'; did you mean 'get_supports_color_temperature'?
95 | traits.set_supports_color_temperature(true);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| get_supports_color_temperature
/config/right-desk-lamp.yaml: In lambda function:
/config/right-desk-lamp.yaml:56:28: error: 'ColorTempRGBWLight' does not name a type
56 | auto light_out = new ColorTempRGBWLight.h(id(output_red), id(output_green), id(output_blue), id(output_white));
| ^~~~~~~~~~~~~~~~~~
/config/right-desk-lamp.yaml:58:24: error: could not convert '{light_out}' from '' to 'std::vectoresphome::light::LightOutput*'
58 | return {light_out};
| ^
| |
|
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_flash_utils.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_i2s.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_main.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_non32xfer.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_noniso.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_phy.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_postmortem.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_si2c.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_sigma_delta.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_spi_utils.cpp.o
Compiling .pioenvs/right-desk-lamp/FrameworkArduino/core_esp8266_timer.cpp.o
*** [.pioenvs/right-desk-lamp/src/main.cpp.o] Error 1
========================== [FAILED] Took 2.38 seconds ==========================
I would love a workaround :C
@panchomira I am no longer using these bulbs, and esphome is no longer compatible with this class.
Nice work! Here is a question - do you know how to set the color of the light at power up?