zigbee2mqtt icon indicating copy to clipboard operation
zigbee2mqtt copied to clipboard

Support Philips Hue Gradients

Open zegl opened this issue 3 years ago • 1 comments

Is your feature request related to a problem? Please describe

Many new Philips hue devices support gradients (I'm counting at least 23 in philips.js, out of which 6 of them support setting gradient_scene).

This has been discussed before in #10674. That discussion ended when the gradient_scene enum was added, and decoding the payload seemed like a dead end. The payload has now been successfully decoded (https://github.com/Koenkk/zigbee2mqtt/issues/10674#issuecomment-1284527609), and we can now build even better support for gradients!

I have a POC running locally, that I'm now planning to send a series of PRs for.

Describe the solution you'd like

I'm planning to add a new philips_hue_multicolor property to supported Philips devices (starting with 915005987201, as that's what I have available for testing with).

The API could look something like this (I have some more testing to do, before committing to the API, feedback is very welcome)

// imports

const encodeHexToPoint = (hex) => {
    const rgb = ColorRGB.fromHex(hex)
    const xy = rgb.toXY()
    const x = xy.x * 4095 / 0.7347
    const y = xy.y * 4095 / 0.8413
    const xx = Math.round(x).toString(16)
    const yy = Math.round(y).toString(16)

    return [
        xx[1], xx[2],
        yy[2], xx[0],
        yy[0], yy[1],
    ].join("")
}

const tzLocal = {
    philips_hue_multicolor: {
        key: ['philips_hue_multicolor'],
        convertSet: async (entity, key, value, meta) => {
            const hexes = value.split(",")
            if (hexes.length !== 5) {
                throw new Error(`Expected 5 colors, got ${hexes.length}`);
            }
            const payload = "500104001350000000" + hexes.map(encodeHexToPoint) + "2800"
            await entity.command('manuSpecificPhilips2', 'multiColor', payload);
        },
    },
};

const definition = {
    zigbeeModel: ['915005987201'],
    ...
    toZigbee: [tzLocal.philips_hue_multicolor, /* etc */],
    exposes: [exposes.text('philips_hue_multicolor', ea.SET)],
    ...
};


module.exports = definition;

After this is done, I'm also planning on adding support to the frontend, to be able to set all color points.

After we have basic 5-point gradients in place, support can be extended with variable point gradients. Most devices seems to support setting 1 to 5 colors, and I suspect that some light strips might support even more color points.

Describe alternatives you've considered

Not using gradients (jk)

Additional context

:-)

zegl avatar Nov 29 '22 14:11 zegl

I have a fully working end-to-end working example now, see the linked PRs. This is my first time hacking around deeper in z2m, any feedback would be very welcome. :-)

zegl avatar Nov 29 '22 17:11 zegl

Just a small question, why philips_hue_multicolor and not philips_hue_gradient?

I think the common nomenclature for these devices is gradient so should this not be used throughout Z2M to prevent ambiguity and confusion?

P.S. great work on this :-)

Implemented in https://github.com/Koenkk/zigbee-herdsman-converters/pull/5049

Koenkk avatar Dec 08 '22 17:12 Koenkk