dresden-elektronik / deconz-rest-plugin

deCONZ REST-API plugin to control ZigBee devices
BSD 3-Clause "New" or "Revised" License
1.9k stars 502 forks source link

Hue gradient lightstrip #5891

Closed ebaauw closed 1 year ago

ebaauw commented 2 years ago

Device

deCONZ already supports this light strip as a regular single-colour lightstrip. The request is, of course, for support of the gradients. In the Hue app, the light strip shows three linked colour points, allowing for three areas with different colours, smoothly transitioning into each other. These gradients are supported only through the Hue API v2.

Screenshots

Basic

Very similar to the Hue outdoor light strip and to the modules in the Hue Ensis, except for the 0xFC03 cluster.

Screenshot 2022-03-19 at 15 08

Identify

Same as other Hue lights.

Groups

Same as other Hue lights.

Scenes

Same as other Hue lights.

On/Off

Same as other Hue lights.

Level Control

Same as other Hue lights.

Color Control

Same as other Hue lights: colour temperature between 153 and 500; colours from gamut-C.

OTAU

Image type 0x0118; I managed to capture the location of the firmaware file and updated https://github.com/dresden-elektronik/deconz-ota-plugin/blob/master/README.md.

FC01

This cluster is present on all Hue colour lights. I don't know what it's for exactly; might be related to Hue Entertainment.

FC03

The Hue bridge uses this cluster to set the gradient colours. It polls attribute 0x0002, which is an octec string, and it sends command 0x00 when changing the gradient from the Hue app. The gradients are supported only by the Hue API v2.

This cluster is also present on the gamut-C E27 bulb, but not on the gamut-A and gamut-B bulbs and spots, and not on the regular light strips.

ebaauw commented 2 years ago

The Hue app shows special animated scenes, Candle and Fireplace. Looks like the animation is handled by the light strip firmware. When selecting Candle, the bridge sends command 0x00 to 0xFC03 with payload 0x200001. For Fireplace, it sends 0x200002. When stopping the animation from the app, payload 0x200000 is sent.

payload meaning
0x200000 stop animation
0x200001 Candle animation
0x200001 Fireplace animation

Attribute 0x0002 seems to encode the light state, where the first two bytes indicate the mode, the next byte OnOff, the next byte Current Level, and the following bytes the mode-specific state. For example:

0b:00:01:fe:05:b1:ec:4e
|     |  |  |     + Current Y: 0x4eec = 0.3083
|     |  |  + Current X: 0xb105 = 0.6915
|     |  + Level: 254
|     + OnOff: on
+ mode 0x000b:`xy`

This is the red-most colour in gamut-C. The attribute reflects this after setting {"xy": [1, 0.0001]} through the APIv1, as well as after setting {"hue": 0, "sat": 254}.

After setting {"ct": 254}, 0x0002 reports:

0f:00:01:fe:fe:00:4c:62:84:61
|     |  |  |     |     + Current Y: 0x6184 = 0.3809
|     |  |  |     + Current X: 0x624c = 0.384
|     |  |  + CT: 254
|     |  + Level: 254
|     + OnOff: on
+ mode 0x000b = `ct`

The Current X and Current Y values match what APIv1 reports for xy while in colormode ct.

After setting Candle:

ab:00:01:54:1c:7a:e8:69:01:80
|     |  |  |     |     + Scene 0x8001 = Candle
|     |  |  |     + Current y: 0x69e8 = 0.4137
|     |  |  + Current X: 0x7a1c = 0.477
|     |  + Level: 0x54 = 33%
|     + OnOff: on
+ mode 0x00ab = Scene

And after setting Fireplace:

ab:00:01:fe:98:8c:7f:68:02:80
|     |  |  |     |     + Scene 0x8002 = Fireplace
|     |  |  |     + Current y: 0x687f = 0.4082
|     |  |  + Current X: 0x8c98 = 0.5492
|     |  + Level: 0xfe = 100%
|     + OnOff: on
+ mode 0x00ab = Scene

After setting {"effect": "colorloop"}, 0x0002 reports the current colour in mode 0x000b.

ebaauw commented 2 years ago

Setting the gradient seems straightforward enough. It's command 0x00 with a payload:

Attribute 0x0002 seems to follow a similar pattern:

However, I have no clue yet how the entries are encoded. 000000 corresponds to 57730e; ffffff to 11ea91

While the Hue app only visualises 3 points, it actually sends 5. I suppose the lines connecting the points are significant as well, relating to the intermediary points.

github-actions[bot] commented 2 years ago

As there has not been any response in 21 days, this issue has been automatically marked as stale. At OP: Please either close this issue or keep it active It will be closed in 7 days if no further activity occurs.

ebaauw commented 2 years ago

Bump

github-actions[bot] commented 2 years ago

As there has not been any response in 21 days, this issue has been automatically marked as stale. At OP: Please either close this issue or keep it active It will be closed in 7 days if no further activity occurs.

ebaauw commented 2 years ago

Bump

manup commented 2 years ago

Small update, the Hue gradient lightstrip is ordered so should be ready for integration soon.

Gloomyeye commented 2 years ago

Do you have something new to the hue gradient integration with more than one light?

nxtshot commented 2 years ago

Would love to see support for Hue Gradient Signe as well. I guess it's based on the same function. If someone need details from that lamp, please ping me :)

github-actions[bot] commented 2 years ago

As there has not been any response in 21 days, this issue has been automatically marked as stale. At OP: Please either close this issue or keep it active It will be closed in 7 days if no further activity occurs.

Gloomyeye commented 2 years ago

Bump

github-actions[bot] commented 2 years ago

As there has not been any response in 21 days, this issue has been automatically marked as stale. At OP: Please either close this issue or keep it active It will be closed in 7 days if no further activity occurs.

ebaauw commented 2 years ago

Ping

github-actions[bot] commented 2 years ago

As there has not been any response in 21 days, this issue has been automatically marked as stale. At OP: Please either close this issue or keep it active It will be closed in 7 days if no further activity occurs.

ebaauw commented 2 years ago

Bump

theCheek commented 2 years ago

Would love to see support for Hue Gradient Signe as well. I guess it's based on the same function. If someone need details from that lamp, please ping me :)

I too have the Gradient Signe, so I'm guessing each zone is not available for control via deconz yet correct? If you need anything from me to help get it working happy to help!

ebaauw commented 2 years ago

It would help to see how the Hue bridge exposes the Signe over API v2. Also, please attach GUI screenshots of the node with endpoints and clusters, and of the Basic (see my initial comment), and check what the Image Type of its firmware is (in the OTAU panel).

theCheek commented 2 years ago

Sorry for the delay on this.

It would help to see how the Hue bridge exposes the Signe over API v2.

Sure things, but how can I do this?

Also, please attach GUI screenshots of the node with endpoints and clusters image

and of the Basic (see my initial comment), image

and check what the Image Type of its firmware is (in the OTAU panel). image

Hope this helps, please let me know anything else I can provide!

ebaauw commented 2 years ago

Please read the attributes before taking the screenshot, so the attribute values are populated. I think there’s a bug in the GUI, that the attribute values of the OTAU cluster aren’t updated, until you select another cluster and then re-select the OTAU cluster. Alternatively, check the OTAU panel instead.

theCheek commented 2 years ago

Apologies but I can't seem to get the attributes to populate to anything different than what I posted above. I've tried pressing the 'read' button that is above cluster info attributes: image but as you can see nothing seems to happen even when selecting a different cluster.

The OTAU panel is showing this: image

ebaauw commented 2 years ago

The OTAU panel is showing this:

Cool.

What about the Basic cluster? We would need at least the Model Identifier.

theCheek commented 2 years ago

I think I managed it: image

Gloomyeye commented 2 years ago

Maybe this could help to fully integrate the hue gradient lightstrip: https://github.com/Koenkk/zigbee2mqtt/issues/10674

ebaauw commented 2 years ago

From what I read, they failed to reverse engineer the encoding of the gradient colour points just as badly?

Gloomyeye commented 2 years ago

Yes, I think so, too. However, they captured few scenes. Maybe this could give a hint in the right direction…

github-actions[bot] commented 2 years ago

As there has not been any response in 21 days, this issue has been automatically marked as stale. At OP: Please either close this issue or keep it active It will be closed in 7 days if no further activity occurs.

ebaauw commented 2 years ago

Ping

github-actions[bot] commented 2 years ago

As there has not been any response in 21 days, this issue has been automatically marked as stale. At OP: Please either close this issue or keep it active It will be closed in 7 days if no further activity occurs.

ebaauw commented 2 years ago

Ping

theCheek commented 2 years ago

what can we do to get this fixed? Happy to do anything necessary!

ebaauw commented 2 years ago

Explain to me how the colour for the gradients is encoded ;-)

ebaauw commented 2 years ago

So I'm pretty certain that each gradient point is encoded in 3 bytes, or 24 bits. The Hue API reports each point with xy values, but I don't understand how these translate to the 3-byte value.

So far I've tested the following hypothesis, none of which seemed to hold:

ebaauw commented 2 years ago

I think I finally cracked it, with help from @manup.

The 3-byte value holds indeed Current X and Current Y as two 12-bit unsigned integers, but the scale differs between Current X and Current Y. X values from 0.7347 onwards and Y values from 0.8431 onwards are encoded as 0xFFF. So the encoded value for X between 0.0000 and 0.7347 is X * 0xFFF / 0.7347. For Y between 0.0000 and 0.8431 it is Y * 0xFFF / 0.8431.

Note that the light strip reports the actual colours displayed, rather than the colours set, so these differ for colours outside gamut C.

ebaauw commented 2 years ago

I'm becoming obsessed by this device.

I noticed the strip includes uint8 attributes 0x0030, 0x0032, 0x0033, 0x0034, 0x0035, and 0x0036 in the Report Attributes message. The non-gradient lights don't seem to carry these.

Doing some more experiments:

Attribute Type RWE Value Meaning
0x0030 u8 re 16* Seems to match pixel_count in the Hue API v2.
0x0031 u16 r 1250 Assumption: pixel length in 0.1 mm - my strip is 2m.
0x0032 u8 rwe 0 ?
Accepts values 0 and 1.
0x0033 u8 rwe 0 Reverse colours.
Accepts values 0 and 1.
0x0034 u8 rwe 1 ?
Accepts values 0 through 3.
0x0035 u8 re 100 ?
0x0036 u8 re 72* Max value for segment byte.

*These are the values without extensions. After adding two extensions, 0x0030 is 32 and 0x0036 is 136.

I think 0x0036 indeed indicates the max number of segments / 8. Note that low bits (for the adjustment) are no longer honoured when segments is at maximum. This seems to be half the number of pixels + 1.

So the colour can be set for every other pixel, the pixels in between make the transition between the set colours. The cut marks (little triangles on the side of the strip), where the strip can be shortened, are every two pixels (or 25cm).

I get the cleanest results when segments divides pixel_count and color_adjustment is 4. In that case, each pixel is clearly distinguishable from the adjacent pixels. With (default) color_adjustment of 0, some adjacent pixels seem to have the same colour.

ebaauw commented 1 year ago

I think the PR is good to go. See the PR for an overview of the new attributes.

$ ph get /lights/5
{
  "capabilities": {
    "alerts": [
      "none",
      "select",
      "lselect",
      "blink",
      "breathe",
      "okay",
      "channelchange",
      "finish",
      "stop"
    ],
    "color": {
      "ct": {
        "computes_xy": true,
        "max": 500,
        "min": 153
      },
      "effects": [
        "none",
        "colorloop",
        "candle",
        "fireplace",
        "loop"
      ],
      "gamut_type": "C",
      "gradient": {
        "max_segments": 17,
        "pixel_count": 32,
        "pixel_length": 1250
      },
      "modes": [
        "ct",
        "effect",
        "gradient",
        "hs",
        "xy"
      ],
      "xy": {
        "blue": [
          0.1532,
          0.0475
        ],
        "green": [
          0.17,
          0.7
        ],
        "red": [
          0.6915,
          0.3083
        ]
      }
    }
  },
  "colorcapabilities": 31,
  "config": {
    "bri": {
      "execute_if_off": false,
      "startup": "previous"
    },
    "color": {
      "ct": {
        "startup": "previous"
      },
      "execute_if_off": true,
      "gradient": {
        "reversed": false
      },
      "xy": {
        "startup": "previous"
      }
    },
    "groups": [
      "0",
      "256"
    ],
    "on": {
      "startup": false
    }
  },
  "ctmax": 500,
  "ctmin": 153,
  "etag": "91984af7f11307099ee62901fd765276",
  "hascolor": true,
  "lastannounced": null,
  "lastseen": "2022-11-04T15:31Z",
  "manufacturername": "Signify Netherlands B.V.",
  "modelid": "LCX004",
  "name": "Hue Gradient",
  "state": {
    "alert": "none",
    "bri": 254,
    "colormode": "xy",
    "ct": 500,
    "effect": "none",
    "gradient": {
      "color_adjustment": 4,
      "offset": 0,
      "offset_adjustment": 0,
      "points": [
        [
          0.6056,
          0.2667
        ],
        [
          0.1533,
          0.0476
        ],
        [
          0.6056,
          0.2667
        ],
        [
          0.1701,
          0.7001
        ]
      ],
      "segments": 16
    },
    "hue": 0,
    "on": false,
    "reachable": true,
    "sat": 254,
    "xy": [
      0.6915,
      0.3083
    ]
  },
  "swversion": "1.97.3",
  "type": "Extended color light",
  "uniqueid": "00:17:88:01:0b:90:7d:12-0b"
}

Set set a gradient:

$ ph put /lights/5/state '{"on": true, "gradient": {"points": [[1, 0], [0, 0]]}}'
{
  "on": true,
  "gradient": {
    "color_adjustment": 0,
    "offset": 0,
    "offset_adjustment": 0,
    "points": [
      [
        0.7347,
        0
      ],
      [
        0,
        0
      ]
    ],
    "segments": 2
  }
}

You see that the API has provided the default values and clipped the xy values.

The light will report the actual colours:

{
  "alert": "none",
  "bri": 254,
  "colormode": "gradient",
  "ct": 500,
  "effect": "none",
  "gradient": {
    "color_adjustment": 0,
    "offset": 0,
    "offset_adjustment": 0,
    "points": [
      [
        0.6056,
        0.2667
      ],
      [
        0.1533,
        0.0476
      ]
    ],
    "segments": 2
  },
  "hue": 62592,
  "on": true,
  "reachable": true,
  "sat": 254,
  "xy": [
    0.6055,
    0.2667
  ]
}
nxtshot commented 1 year ago

@ebaauw awesome work, thanks a lot! Do you know if this will work for the Hue gradient signe as well?

ebaauw commented 1 year ago

Yes, it should. @Thomas-Vos provided me with the model IDs of the SIgne and PLAY gradient lightstrips, in https://github.com/dresden-elektronik/deconz-rest-plugin/pull/6316#issuecomment-1286269191. If you have another, please report it. It should also work with the gradient tube light, as soon as we'll have identified and whitelisted its model ID.

I would interested to know what (gradient) capabilities the Signe exposes. I think there might be a difference between the floor and table models. Thomas mentioned on Discord that his floor model reports pixel_count as 10 (on the Hue v2 API) and, experimentally, supports up to 9 segments. His light strip with three extensions reports a pixel_count of 40. Hoping to receive the extensions I ordered today to do some testing myself.

nxtshot commented 1 year ago

I have a floor model (915005987201), so I guess there is nothing I can provide which you don't know yet, right? I have a hue bridge somewhere around, wouldn't be much of effort to reactivate it.

ebaauw commented 1 year ago

@nxtshot I would appreciate the values of the 0x0030 - 0x0036 attributes in the FC03 cluster. These will also be reported under the light capabilities once my PR will be merged.

macmanroy commented 1 year ago

Yes, it should. @Thomas-Vos provided me with the model IDs of the SIgne and PLAY gradient lightstrips, in #6316 (comment). If you have another, please report it. It should also work with the gradient tube light, as soon as we'll have identified and whitelisted its model ID.

I would interested to know what (gradient) capabilities the Signe exposes. I think there might be a difference between the floor and table models. Thomas mentioned on Discord that his floor model reports pixel_count as 10 (on the Hue v2 API) and, experimentally, supports up to 9 segments. His light strip with three extensions reports a pixel_count of 40. Hoping to receive the extensions I ordered today to do some testing myself.

I have the signe table lamp, it reports a points_capable value of 5 and a pixel_count of 4

ebaauw commented 1 year ago

Here's the gradient light strip with the latest commits:

{
  "capabilities": {
    "alerts": [
      "none",
      "select",
      "lselect",
      "blink",
      "breathe",
      "okay",
      "channelchange",
      "finish",
      "stop"
    ],
    "bri": {
      "min_dim_level": 0.01
    },
    "color": {
      "ct": {
        "computes_xy": true,
        "max": 500,
        "min": 153
      },
      "effects": [
        "none",
        "colorloop",
        "candle",
        "fireplace",
        "loop",
        "sunrise"
      ],
      "gamut_type": "C",
      "gradient": {
        "max_segments": 17,
        "pixel_count": 32,
        "pixel_length": 1250,
        "styles": [
          "linear"
        ]
      },
      "modes": [
        "ct",
        "effect",
        "gradient",
        "hs",
        "xy"
      ],
      "xy": {
        "blue": [
          0.1532,
          0.0475
        ],
        "green": [
          0.17,
          0.7
        ],
        "red": [
          0.6915,
          0.3083
        ]
      }
    }
  },
  "colorcapabilities": 31,
  "config": {
    "bri": {
      "execute_if_off": true,
      "startup": "previous"
    },
    "color": {
      "ct": {
        "startup": "previous"
      },
      "execute_if_off": true,
      "gradient": {
        "reversed": false
      },
      "xy": {
        "startup": "previous"
      }
    },
    "groups": [
      "0",
      "256"
    ],
    "on": {
      "startup": false
    }
  },
  "ctmax": 500,
  "ctmin": 153,
  "etag": "0e049444c9a57c6cf8a1aa29d595ddf0",
  "hascolor": true,
  "lastannounced": null,
  "lastseen": "2022-11-20T15:15Z",
  "manufacturername": "Signify Netherlands B.V.",
  "modelid": "LCX004",
  "name": "Hue Gradient",
  "productid": "Philips-LCX004-1-GALSECLv1",
  "state": {
    "alert": "none",
    "bri": 232,
    "colormode": "gradient",
    "ct": 366,
    "effect": "sunrise",
    "gradient": {
      "color_adjustment": 5,
      "offset": 30,
      "offset_adjustment": 0,
      "points": [
        [
          0.4572,
          0.41
        ],
        [
          0.4531,
          0.4089
        ],
        [
          0.4488,
          0.4079
        ],
        [
          0.4531,
          0.4089
        ],
        [
          0.4572,
          0.41
        ]
      ],
      "segments": 26,
      "style": "linear"
    },
    "hue": 8415,
    "on": false,
    "reachable": true,
    "sat": 140,
    "xy": [
      0.4571,
      0.4099
    ]
  },
  "swconfigid": "F03CAF4D",
  "swversion": "1.97.3",
  "type": "Extended color light",
  "uniqueid": "00:17:88:01:0b:90:7d:12-0b"
}

Note that this is the state that the light strip reports after the sunrise timed effect has finished. I don't know if it's valid (note the 26 segments. The Hue bridge exposes the style as Linear (interpolated_palette), but the raw value is 0x01 instead of 0x00. I tried setting that raw value, but that doesn't seem to take.

github-actions[bot] commented 1 year ago

As there has not been any response in 21 days, this issue has been automatically marked as stale. At OP: Please either close this issue or keep it active It will be closed in 7 days if no further activity occurs.

ebaauw commented 1 year ago

Bump

Gloomyeye commented 1 year ago

Hello @ebaauw, I installed the newest stable version of deconz and I thought that I can switch on parts of my lightstrip via Home Assistant (2023.2). However, my installed Hue lightstrip LCX004 is only shown as one light entity in Home Assistant and I have no idea how I can use the gradient points. Is that possible or do I need to change something in deconz for that?