Skip to content

Conversation

BetaRavener
Copy link
Contributor

@BetaRavener BetaRavener commented Feb 17, 2024

Proposed change

Adds a new, manufacturer specific, Philips cluster that is used to set effects on certain Hue devices, such as Hue Go.

Additional information

Fixes #2517.

Checklist

  • The changes are tested and work correctly
  • pre-commit checks pass / the code has been formatted using Black
  • Tests have been added to verify that the new code works

@BetaRavener BetaRavener force-pushed the feature/hue_effect_cluster branch from 1f7385c to bcfea78 Compare February 17, 2024 17:43
Copy link

codecov bot commented Feb 17, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.87%. Comparing base (57bcec8) to head (9b5d8ae).
Report is 28 commits behind head on dev.

Additional details and impacted files
@@           Coverage Diff           @@
##              dev    #2989   +/-   ##
=======================================
  Coverage   89.86%   89.87%           
=======================================
  Files         322      323    +1     
  Lines       10387    10395    +8     
=======================================
+ Hits         9334     9342    +8     
  Misses       1053     1053           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

0x00: foundation.ZCLCommandDef(
"set_effect",
schema={
"param1": t.uint8_t,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we know what these params represent?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know they were just snooped from the Hue gateway. I've commented on the original issue where I found some additional behavior. The param1 seems to act like some kind of a command ID, and then the rest of params behave different based on that, but that's as much as I managed to observe.

@TheJulianJES
Copy link
Collaborator

Thanks for the PR! Adding custom Hue effects to ZHA is also on my list of things to do eventually.
There's also the new HA EFFECT_OFF that should be added to ZHA, and improve the current effect logic in general.

We'd also need to add the (two) custom effects to ZHA, but only for the Hue lights. This can be done by matching a HueEffectLight class using a quirk_id set in the quirks.

Ideally, I want to avoid matching all Hue light models in quirks individually. We had this in the past for "startup options" (now part of ZCL) and there are way more models now.
IMO, it should be enough to just match by the two manufacturer name (Signify [...]/Philips) and by the signature (correct custom clusters / device type).

I think that this is fine for an initial implementation though. Like mentioned, giving the command params a more descriptive name would be good.

cluster_id = 0xFC03
ep_attribute = "philips_effect"

server_commands = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, we should also use the new "zigpy command definition style", similar to this:
https://github.com/zigpy/zigpy/blob/1853ce109de5d1528333e9c78c325131f8aeed3a/zigpy/zcl/clusters/general.py#L570-L573

Comment on lines 62 to 64
242: {
PROFILE_ID: 41440,
DEVICE_TYPE: 97,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for profile id and device type, use this:

            242: {
                PROFILE_ID: zgp.PROFILE_ID,
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
            },

(and also for the replacement section)

@BetaRavener
Copy link
Contributor Author

Regarding the effect for ZHA, I have commented on the issue trying to piece the information together from source code. Eventually, I've arrived at something like (saved in /usr/src/homeassistant/homeassistant/components/zha/light.py in docker container):

@STRICT_MATCH(
    cluster_handler_names=CLUSTER_HANDLER_ON_OFF,
    aux_cluster_handlers={CLUSTER_HANDLER_COLOR, CLUSTER_HANDLER_LEVEL, "philips_effect"},
    manufacturers={"Philips", "Signify Netherlands B.V."},
)
class EffectHueLight(Light):
    """Representation of a HUE light with effects."""
    def __init__(
        self, unique_id, zha_device: ZHADevice, cluster_handlers, **kwargs
    ) -> None:
        """Initialize the ZHA light."""
        super().__init__(unique_id, zha_device, cluster_handlers, **kwargs)
        self.error("Matched EffectHueLight")
        self._effect_cluster_handler = self.cluster_handlers.get("philips_effect")
        self._attr_effect_list.append("candle")
        self.error("%s", str(self._effect_cluster_handler.set_effect))

    async def async_turn_on(self, **kwargs: Any) -> None:
        await super().async_turn_on(**kwargs)
        effect = kwargs.get(light.ATTR_EFFECT)
        self.error("%s", str(effect))        
        if effect == "candle":
            await self._effect_cluster_handler.set_effect(
                param1=33,
                param2=0,
                param3=1,
                param4=1,
            )

This does work - it adds the new effect on Hue Go, and selecting it turns the effect on, but it kind of breaks the HA state - for example it's possible to change brightness when the effect is on, but turning the effect on with this command causes the lamp to switch to set (but unknown) brightness, so the brightness slider is now not in sync with actual lamp brightness,

As you can see in ZHA I match against the Effect cluster, so all lamps that support it will have this. However on zigpy side, you still need to make the quirk itself apply to specific lights that we know actually support the effects. Or do you plan to apply the quirk to all bulbs that report the 0xFC03 cluster? Is that possible somehow?

@@ -0,0 +1,97 @@
"""Philips Hue Go 7602031P7 device."""
Copy link
Collaborator

@dmulcahey dmulcahey Mar 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a new way to define quirks now. I still need to write documentation for it but I think we can replace the majority of this file with:

from zhaquirks.philips import PHILIPS, PhilipsEffectCluster
from zigpy.quirks.v2 import add_to_registry_v2

(
    add_to_registry_v2(
        PHILIPS, "7602031P7"
    )
    .replaces(PhilipsEffectCluster, endpoint_id=11)
)

@dmulcahey
Copy link
Collaborator

dmulcahey commented Mar 1, 2024

Here is a complete self contained example tested as a custom quirk on my dev instance with model: 7602031U7

note this will require a new release of zigpy w/ the bug fix here: zigpy/zigpy#1348 https://github.com/zigpy/zigpy/releases/tag/0.63.3

"""Test Hue Go v2."""

from typing import Final

from zigpy.quirks import CustomCluster
from zigpy.quirks.v2 import add_to_registry_v2
import zigpy.types as t
from zigpy.zcl import foundation

PHILIPS = "Philips"


class PhilipsEffectCluster(CustomCluster):
    """Philips effect cluster."""

    cluster_id = 0xFC03
    ep_attribute = "philips_effect"

    class ServerCommandDefs(foundation.BaseCommandDefs):
        """Server command definitions."""

        set_effect: Final = foundation.ZCLCommandDef(
            id=0x00,
            schema={
                "param1": t.uint8_t,
                "param2": t.uint8_t,
                "param3": t.uint8_t,
                "param4": t.uint8_t,
            },
            direction=foundation.Direction.Client_to_Server,
            is_manufacturer_specific=True,
        )


(
    add_to_registry_v2(PHILIPS, "7602031P7")
    .also_applies_to(PHILIPS, "7602031U7")
    .replaces(PhilipsEffectCluster, endpoint_id=11)
)

Copy link

There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. Thank you for your contributions.

@github-actions github-actions bot added stale Issue is inactivate and might get closed soon and removed stale Issue is inactivate and might get closed soon labels Aug 28, 2024
@jtbandes
Copy link
Contributor

Hi there, just curious if there are clear next steps on this PR? Any help needed with testing?

@BetaRavener
Copy link
Contributor Author

I was on a long trip and just recently came back. The next step I suppose is to test if @dmulcahey implementation can replace my original one on current version, I'd hope that the changes he mentioned before already made it all the way to HA.

@barti04
Copy link

barti04 commented Dec 22, 2024

Hi there,
I just stumbled upon this PR, and it looks like it has become stale for quite a while. Is there anything this PR is missing that I could help with @BetaRavener @dmulcahey?

@BetaRavener
Copy link
Contributor Author

BetaRavener commented Dec 22, 2024

I promise to test it out on my Philips Go and HA on 6th of January. If anyone else wants to contribute by then, testing other devices would be definitely nice. Thank you for the interest :)

@barti04
Copy link

barti04 commented Dec 23, 2024

That's great to hear. I will see what I can do about testing on other devices.

@BetaRavener BetaRavener force-pushed the feature/hue_effect_cluster branch from bcfea78 to 43fe70b Compare January 12, 2025 17:15
@BetaRavener BetaRavener force-pushed the feature/hue_effect_cluster branch from 43fe70b to 2cadec6 Compare January 12, 2025 17:26
@BetaRavener
Copy link
Contributor Author

Please excuse the delay but today I managed to find some time.
I had to change add_to_registry_v2 to QuirkBuilder as that now seems to be preferred way to implement quirks.

I've tested it on my Hue and it works nicely. I've just left the Effect cluster in __init__.py as I expect more Hue devices would support it.

image

@dmulcahey @TheJulianJES would you be please so kind to review the PR once more?

@kjagiello
Copy link
Contributor

kjagiello commented Jan 20, 2025

Just stumbled upon this PR and wanted to mention that I have also been working on this recently, though I took a slightly different approach and set up the 0x0 command schema so that both the effects and gradients can be controlled. See here: #3664

@BetaRavener
Copy link
Contributor Author

Ah that's cool @kjagiello . So Philips reused the same cluster/endpoint for another feature and expanded the content byte length... I'd test your approach with the Go lights and if all works well we could merge the code into your PR.

@BetaRavener
Copy link
Contributor Author

BetaRavener commented Jan 21, 2025

I've tried it out and it works nicely with Go, so I'm okay switching to your PR to reduce conflicts and number of reviews. I've opened PR against your fork kjagiello#1 that you can merge to simply get my changes on top.

The usage example changes to this:
image

@kjagiello
Copy link
Contributor

Great to hear that it worked! Merged your changes now.

@BetaRavener
Copy link
Contributor Author

Closing in favor of #3664 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Device Support Request] Hue bulbs missing Candle Effect
6 participants