enwi / hueplusplus

A simple C++ library to control Philips Hue lights on Linux, MacOS, Windows, Espressif ESP32 SDK and Arduino. Full documentation at
https://enwi.github.io/hueplusplus/
GNU Lesser General Public License v3.0
53 stars 22 forks source link

Add Philips LCA003 and LCB001 and issues with color conversion #57

Closed CalcProgrammer1 closed 3 years ago

CalcProgrammer1 commented 4 years ago

I just bought a Hue bulb to use for developing with this library and it appears to be unsupported. The bulb model shows up as "LCA003". It is a white+color bulb with Bluetooth and ZigBee that I bought at Home Depot. I modified Hue.cpp to add LCA003 to the group starting with LCT001 and it works, but I'm not sure if this is the right place for it (specifically what ColorType it uses).

Jojo-1000 commented 4 years ago

Thank you for using our library, I hope you like it so far. The issue with only a few supported devices is fixed on the development branch. That uses information from the bridge to identify the type, so it is unnecessary to add all of them manually.

I would appreciate if you could check it out and verify that it works, because obviously we don't have a ton of different lights to test with.

In general, the development branch has a lot more features and should be reasonably stable. The only reason why it is not merged yet is that there are a lot of breaking changes, and we would like to sort out a versioning system first.

CalcProgrammer1 commented 4 years ago

Sounds good, I will check out the development branch!

CalcProgrammer1 commented 4 years ago

Ok, I updated my code to use the development branch, but it crashes when it connects to the bridge with:

Could not determine Light color type:LCA003!

Edit: I am using a V1 bridge. It's also setting certain colors very dim no matter what gamut I add LCA003 to on this branch. Red and blue (255/0/0, 0/0/255) are extremely dim but yellow and cyan are fine.

void PhilipsHueController::SetColor(unsigned char red, unsigned char green, unsigned char blue)
{
    hueplusplus::RGB rgb;
    rgb.r = red;
    rgb.g = green;
    rgb.b = blue;

    light.setColorRGB(rgb, 0);
}
Jojo-1000 commented 4 years ago

So, does your bridge version not have a capabilities attribute for the lights, or is it not parsed correctly?

For the colors, I think that is caused by the calculation from rgb colors to xy. Previously it was only changing the color, but it was changed to also change the brightness depending on the rgb brightness (that is how they suggest it in the docs).

Edit: Although it seems from their original code, that they do not update the brightness of the light based on the Y component, so maybe that was a misunderstanding by me. It definitely seems off that a full red is only 30% brightness or so.

CalcProgrammer1 commented 4 years ago

I'm not sure what capabilities it has, but it looks like the returned value is null that is checked to determine the gamut. It falls in to the code that looks up the model name in the list. I got this bridge for 25 cents on ebay because I wanted something to add Hue integration into my app with, didn't realize the v1 bridge was discontinued and out of service. Luckily I don't care about the cloud stuff so having that part unavailable doesn't bother me.

I do notice that with the old version of the library, the brightness seems inconsistent when going through a rainbow pattern. I'm controlling the light with a music visualizer that has a rainbow background mode. My other lights are fine, but the Hue bulb brightness jumps around a lot (it's also quite choppy, but I read that Hue is limited to 10 updates/sec outside of entertainment mode so I guess that's to be expected).

I'm going to try using Razer's Hue integration in Razer Synapse as that should be able to sync the Hue lights with fast paced game effects, and I have an old version of my visualizer that uses Razer's SDK.

Edit: Razer Synapse does not detect my bridge. I'm guessing that the V1 doesn't offer that functionality. I did notice that using the development library updates the bulb at a bit faster rate, though the brightness issue is still there.

enwi commented 4 years ago

Seems like there is an issue with the older hue bridge.

Also @Jojo-1000 we should also consider adding the streaming API ("hue entertainment api") to this library, but that might need a rework of this library to function correctly: https://developers.meethue.com/develop/hue-entertainment/philips-hue-entertainment-api/

enwi commented 4 years ago

Also @CalcProgrammer1 what happens if you try the following?

light.setBrightness(255);
light.setColorLoop(true);
CalcProgrammer1 commented 4 years ago

If I set the color loop it does work, the bulb cycles through colors on its own.

Jojo-1000 commented 4 years ago

To speed up the updates, you can change the value of bridgeRequestDelay in LibConfig.h and see if the bridge can handle it. We had some problems with that in the past, so if you get disconnects it is probably because of too many requests per second.

CalcProgrammer1 commented 4 years ago

I'll try that. I'm also investigating using the HSV model instead of XY as it looks like the bulbs can natively accept HSV (hue, sat, bri). I'm trying a build where I convert RGB to HSV and send that.

I noticed that either method has an issue with sending black (0, 0, 0). If I send black more than once it seems to alternate between off and very dim on whatever color it's set to, with a transition even though I have transitions disabled.

Jojo-1000 commented 4 years ago

Yes there is an problem with black, it spits out NaN as x and y, so that could be an issue there.

It also sees that the light is off and xy is sent, so it assumes it should be turned on even though there is a brightness of 0 also set. Should be an easy fix.

CalcProgrammer1 commented 4 years ago

Here is the function I wrote for RGB to HSB with the Philips Hue quirks for red, green, and blue points. It seems to be working pretty decently for me. I might try to do a side-by-side comparison between RGB->HSB and RGB->XYB and see which one works better, if there is a difference at all.

HueSaturationBrightness RGB::toHSB() const
{
    const uint8_t cmax = std::max(r, std::max(g, b));
    const uint8_t cmin = std::min(r, std::min(g, b));
    const float diff = cmax - cmin;

    float h = -1;
    float s = -1;

    if(cmax == cmin)
    {
        h = 0;
    }
    else if(cmax == r)
    {
        h = (int)(9307 * ((g - b) / diff) + 65535) % 65535;
    }
    else if(cmax == g)
    {
        h = (int)(12750 * ((b - r) / diff) + 25500) % 65535;
    }
    else if(cmax == b)
    {
        h = (int)(10710 * ((r - g) / diff) + 46920) % 65535;
    }

    if(cmax == 0)
    {
        s = 0;
    }
    else
    {
        s = (diff / cmax) * 254;
    }

    HueSaturationBrightness hsb;
    hsb.hue = h;
    hsb.saturation = s;
    hsb.brightness = cmax;

    return(hsb);
}

Only thing now is that the brightness doesn't seem to be quite the same as my other RGB devices. For most RGB devices, the brightness seems to increase when combining channels (i.e. yellow [255, 255, 0] looks brighter than red [255, 0, 0]). I have an effect I use in my visualizer that is a sinusoidal rainbow - red, green, and blue are all sine waves offset by 120 degrees. This has the mathematical property that the combined output should always be the same as all channels add up to 1 if I remember right.

The Hue bulb seems to be trying to correct for this behavior internally, which means it looks different than most RGB devices. I took a quick video comparing the Hue bulb to an Espurna-flashed AiLight which is taking in raw RGB values from E1.31.

https://gfycat.com/TautNeglectedBluegill

CalcProgrammer1 commented 4 years ago

Just got another bulb that needs to be added. This one is an LCB001, it's the new model BR30 floodlamp-style white and color bulb with Bluetooth.

Jojo-1000 commented 4 years ago

I made some changes and fixed the flickering issue, and also changed the behavior for types which are unknown. Instead of throwing an exception, it only prints a warning so you can continue to use the light. You can check out fix-issue-57 and try it.

If you want to add them anyway (feel free to do a PR), most of the newer Hue lights should have gamut C, when they are labeled as "Rich Color". Edit: Maybe they are also the same as the LCT* variants, the A or B seems to indicate bluetooth support.

CalcProgrammer1 commented 3 years ago

I'll try to get a PR soon. I haven't messed with the Hue stuff in a few weeks and it's been sitting in a branch of my project gathering dust. I think I'll have some time to dig into it some more after this week.

CalcProgrammer1 commented 3 years ago

I submitted a PR to add these bulb types. Both packages have the Richer Colors stamp on them so I put them in the C gamut. I have a Hue Bridge V2.1 on the way and hope to do some experiments with the entertainment mode once it gets here as I'm having update rate troubles with the V1 bridge.

If I only am controlling a single light, I can update at 10Hz (100ms delay, library unchanged) reliably, but if I try to control 2 or more my program crashes after at most a few minutes of working.

I was using two Hue bulbs for Halloween lighting and was feeding in data from an E1.31 light control software to my program, the continuous updates resulted in frequent crashing. Ended up just setting the Hue lights to static colors and leaving them out of the sequence. Has anyone researched/reverse engineered the entertainment mode yet?

enwi commented 3 years ago

@CalcProgrammer1 The Bridge V2.1 is the BSB002 right? I have that one too, so I could help testing the streaming API.

Jojo-1000 commented 3 years ago

I changed the XYBrightness calculation to match the brightness of your HueSaturationBrightness function. It is on the branch fix-issue-57. @CalcProgrammer1 Could you check whether the new calculation produces the correct colors?

CalcProgrammer1 commented 3 years ago

I will try to test it this week/weekend but I've been busy recently and haven't revisited Philips Hue in OpenRGB for a few months now.