How to handle LED strip and keep color separate from brightness

I am trying to modify a driver for a wifi LED strip but running into issues with the setColor COLOR_MAP because it seems to force that the third value is pulled from "level". This LED strip uses a RBG value to set the color, and 'brightness' for the brightness. I have tested it and the color can definitely be independent of the brightness. The issue comes in especially if you change things using the app, you can end up with a RGB value that translates to a 50 V in the HSV conversion, but the strip could be at any brightness level 1-100. Or alternately you can have a color with 100V (pure red) but set it to 50% brightness. So when I refresh the device from Hubitat the color picker and dashboard then do not show the color correctly.

Why is the COLOR_MAP tied to level? Shouldn't it be something like luminance or lightness? Is there any way I can re-write the setColor command in my code and force it to use another attribute besides 'level' for the third value? I think that would 100% solve the problem.

Another observation, if I share this device to Hubitat via its own skill then I get a "Brightness" slider along with a color picker. If I share it via Hubitat I get a "Power Level" slider and a color picker.

Despite the naming in colorMap, Hubitat seems to use HSV, with another important difference being that the hue parameter is expressed in a range of 0..100 rather than 0..360, presumably for legacy compatibility reasons. More discussion in this thread:

With that in mind, my advice is to ignore the 'level' naming with any relationship to the brightness level in dimmer terms. And use it as the V value in an HSV converter to get RGB colors (or whatever you need).

Yes this is what I had suspected after some reading on the forum earlier with the HSV. I thought about storing the brightness in a separate 'brightness' attribute but then I dont think you can expose it to a dashboard or Alexa as a brightness slider. This is very unfortunate how they chose to implement the color_map... simply using another attribute for the "V" would have solved it I think.

The only other solution I can think of would be create a child device just to handle either the brightness or the color_map so it could be set as the level there. Which that seems like a terrible idea as well. You could at least control and see the brightness independently of the color this way but it would take up two dashboard tiles.

I'm not sure if your problem is that Hubitat's color model is HSV/HSB, as mentioned above (and not HSL as you might expect from the "level" attribute), or that you're only looking to set the first two of these and not the third. In that case, wouldn't the individual setHue() and setSaturation() commands work, or could you modify your setColor() implementation (since it sounds like it's your own driver) to just set these two attributes if level is not provided?

If it's the former problem instead, I suppose that is harder to solve. :slight_smile: But you could steal the device's current level value (if not provided) and do HSV to HSL conversion with, it I suppose. (Or are you saying that that is what the driver is doing? Nothing should do that by default--setColor() only does what you tell it to.) Or: I'm pretty sure that at least the hue values should line up between the two color models regardless of the other two (warning: not a color model expert) so at least setHue() should work if that's all you need.

@bertabcd1234 The device uses RGB value to set the color and a separate brightness for the... brightness. So HSL/HSV I dont really care what the values mean its just there to make the setColor color map work and let me pick a color. I am converting back and forth to RBG using the built in colorUtils methods.

The problem is that if the device is controlled from outside hubitat and then I refresh the device I now have two different values that are both supposed to be in the 'level' attribute. The brightness, and the third value from the RBG conversion. If I ignore that third value and set the level according to the brightness then the setColor colormap thinggy uses the level value to show the color which is now incorrect for the RBG value of the LEDs.

If I pick a color from the color map I could send the proper RBG values to the LED but where do I save the third value? If I save it in level so that the colormap shows the correct thing, now my brightness may be incorrect. If I don't save it then the colormap will refresh using the brightness (level) for the third value.

In summary: the entire problem revolves around that the brightness (level) and the "V" from the HSV value in the colorMap are BOTH supposed to be saved in the 'level' attribute.

Interesting! It seems odd to me that the light would track RGB and brightness separately considering that the values of the RGB values themselves have that information built into them (and Hubitat's rgbToHSV() method should convert that). If the values that the light reports don't align with those, it seems like maybe it is the odd one here. Your idea of using a child device (or custom attribute and command) or other method of reporting and setting this value seems like a workaround you could use in this case, though if I were a user of the device, I'm not sure how I'd know what means what. :slight_smile:

My advice: regardless of the naming in colorMap, you're under no obligation to save the level/value term. Use it to set RGB and then drop it. Then support dimmerLevel to actually get the level attribute input that represents the brightness.

I will need to test the lights at RBG 255,0,0 (pure red) with 100% brightness, 255,0,0 / 50% and then also 128,0,0 / 100% and 128,0,0 / 50%.

In theory 255,0,0 / 50% should be the same visible light as 128,0,0 / 100% correct?

Maybe there is a formula I can work out to combine the RBG and brightness into a single valid RBG / HSV map.... hmmm....

This is a good reference, particularly the 'Color Conversion Formulae' section. The level/value attribute in HSL/HSV is a different concept from brightness in the dimmer sense.

Yes and I know it is trivial but then if you refresh the page the color displayed on the color picker will now use the current level value instead of the one you just set. Little things like that leave it un-polished and unacceptable to me.

Yeah, that's what's confusing--those last ones aren't aren't really a thing: 128,0,0 is 50% brightness (but 255,0,0 is indeed red at 100% brightness); the brightness is built in to the RGB values, and that's how they convert to HSV/HSB, so I don't know what this strip is expecting for input or what it's telling you with this output if it doesn't line up with what is supposedly RGB.

I don't have anything using Hubitat's built-in conversion methods handy, but I suspect they would tell you the same when converted to HSV. They should already be "combining" brightness into the conversion because that's how it works.

I don't know this, but I suspect that the color picker is populated using the RGB attribute. In my drivers that support colorControl, the color picker follows whatever I set the color to previously. And that is with only sendng hue and saturation attribute events, not level (aka value) in response to color settings changes.

Edit: check out the driver code that I PMed to you. It behaves correctly as far as I can tell, and even though the actual device interactions will differ for your device, the example might still be valid to illustrate my suggestions here.

Maybe if the RGB attribute is set correctly then it will use that? Currently my driver is for sure using the hue, saturation, and level values to set the color shown. It originally did not have the RGB attribute being populated and the documentation only says "string" so I was not sure what to set it to. Looks like in the example you sent me via PM you are setting a map in there, I will have to try something like that (tomorrow) and see if it helps.

sendEvent(name: "RGB", value: [red:, green:, blue:])

1 Like

Yeah, I think I teased out that detail by inspecting the behavior of one of the native Hubitat drivers, since as you pointed out the documentation ("string") was a bit lacking on what the format should be. Give it a try and see what works. Good luck!

Edit: @jtp10181 , on second thought, it is also possible that color might influence the color picker. Again based on testing, I discovered that the 'string' value there should actually be a map of the same format as specified in the setColor command parameter. So, I would suggest setting both of those attributes in the format I used in the driver code I sent and then see if it addresses your color picker issue.

No dice, it is still using the 'level' aka brightness in the color picker. Yes my daughter has her room set to RED as low as it goes....

According to the color picker this should be the equivalent of 3,0,0 which is basically black, but the light is actually red, just very low.



Edit: nevermind, you were totally right. When I refresh the page the color picker changes to match the level attribute. I suspect this is just an unfortunate/unintended behavior of the device page in Hubitat. Or someone along the way (possibly including myself) misunderstood how these are supposed to be related. But I find it hard to believe that the V parameter in the HSV value would be intended to be applied to the level value related to brightness, since that term is part of specifying the color, not the illuminance level of the bulb.

Sorry for the runaround and confusion that I introduced.

Maybe @mike.maxwell would have some history or advice on this topic?

This is my thoughts exactly, but that is how they have it setup!

1 Like

As a temporary solution I have set the driver up to use a custom attribute 'brightness' for the brightness so the level can be used for the HSV values which drive the color picker.

Doing some research on Smart Things with this the info I found seemed to point to the color picker on ST only using the HUE and SAT values which also seems to coincide with how the LED strip app works as well.

I am still thinking there should be some formula where I can take the RGB values and the brightness from the device and combine it to get an accurate HSV.

Obviously it's your preference for your driver, but I'd personally prefer the color picker to be wrong before the brightness was in a non standard attribute, because the latter would make things like dimmerLevel sliders on a dashboard be incorrect.

As for converting from RGB to HSV (and back), it's actually relatively straightforward. You don't even need the brightness term. The 'V' term, for example, is just equal to the maximum of the R,G,B terms. Others are only slightly more complicated: HSL and HSV - Wikipedia

Just remember if you make your own versions of these that Hubitat expresses hue on a 0..100 scale.

Download the Hubitat app