Skip to content
Open
96 changes: 94 additions & 2 deletions zhaquirks/candeo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
"""Module for Candeo quirks implementations."""

import math
from typing import Final

from zigpy.quirks import CustomCluster
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic
from zigpy.zcl.clusters.general import Basic, LevelControl, OnOff
from zigpy.zcl.clusters.lighting import Color
from zigpy.zcl.clusters.measurement import IlluminanceMeasurement
from zigpy.zcl.clusters.security import IasZone
from zigpy.zcl.foundation import DataTypeId, ZCLAttributeDef
from zigpy.zcl.foundation import (
BaseCommandDefs,
DataTypeId,
ZCLAttributeDef,
ZCLCommandDef,
)

from zhaquirks.const import ZONE_TYPE

CANDEO = "Candeo"
COMMAND_PRESS = "press"
COMMAND_DOUBLE_PRESS = "double_press"
COMMAND_HOLD = "hold"
COMMAND_RELEASE = "release"
COMMAND_STARTED_ROTATING = "started_rotating"
COMMAND_CONTINUED_ROTATING = "continued_rotating"
COMMAND_STOPPED_ROTATING = "stopped_rotating"


class CandeoSwitchType(t.enum8):
Expand All @@ -21,6 +35,13 @@ class CandeoSwitchType(t.enum8):
Toggle = 0x01


class CandeoRemoteDirection(t.enum8):
"""Candeo Remote Direction."""

Right = 0x00
Left = 0x01


class CandeoIlluminanceMeasurementCluster(IlluminanceMeasurement, CustomCluster):
"""Candeo Illuminance Measurement Cluster."""

Expand Down Expand Up @@ -77,3 +98,74 @@ class CandeoIasZoneWaterCluster(IasZone, CustomCluster):
"""Candeo IasZone Water Cluster."""

_CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Water_Sensor}


class CandeoRGBColorCluster(Color, CustomCluster):
"""Candeo RGB Color Cluster."""

_CONSTANT_ATTRIBUTES = {
Color.AttributeDefs.color_capabilities.id: Color.ColorCapabilities.XY_attributes,
Color.AttributeDefs.color_temperature.id: None,
Color.AttributeDefs.start_up_color_temperature.id: None,
}


class CandeoCCTColorCluster(Color, CustomCluster):
"""Candeo CCT Color Cluster."""

_CONSTANT_ATTRIBUTES = {
Color.AttributeDefs.color_capabilities.id: Color.ColorCapabilities.Color_temperature
}


class CandeoRGBCCTColorCluster(Color, CustomCluster):
"""Candeo RGBCCT Color Cluster."""

_CONSTANT_ATTRIBUTES = {
Color.AttributeDefs.color_capabilities.id: Color.ColorCapabilities.XY_attributes
+ Color.ColorCapabilities.Color_temperature
}


class CandeoOnOffRemoteCluster(OnOff, CustomCluster):
"""Candeo OnOff Remote Cluster."""

class ServerCommandDefs(BaseCommandDefs):
"""overwrite ServerCommandDefs."""

double_press: Final = ZCLCommandDef(
id=0x00,
schema={},
)
press: Final = ZCLCommandDef(
id=0x01,
schema={},
)
hold: Final = ZCLCommandDef(
id=0x02,
schema={},
)
release: Final = ZCLCommandDef(
id=0x03,
schema={},
)


class CandeoLevelControlRemoteCluster(LevelControl, CustomCluster):
"""Candeo LevelControl Remote Cluster."""

class ServerCommandDefs(BaseCommandDefs):
"""overwrite ServerCommandDefs."""

started_rotating: Final = ZCLCommandDef(
id=0x05,
schema={"direction": CandeoRemoteDirection},
)
continued_rotating: Final = ZCLCommandDef(
id=0x06,
schema={"direction": CandeoRemoteDirection},
)
stopped_rotating: Final = ZCLCommandDef(
id=0x03,
schema={},
)
103 changes: 103 additions & 0 deletions zhaquirks/candeo/rotary_dimmer_switches.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""Candeo rotary dimmer switches."""

from zigpy.quirks.v2 import QuirkBuilder
from zigpy.zcl import ClusterType
from zigpy.zcl.clusters.general import Identify, Ota

from zhaquirks.candeo import (
CANDEO,
COMMAND_CONTINUED_ROTATING,
COMMAND_DOUBLE_PRESS,
COMMAND_HOLD,
COMMAND_PRESS,
COMMAND_RELEASE,
COMMAND_STARTED_ROTATING,
COMMAND_STOPPED_ROTATING,
CandeoLevelControlRemoteCluster,
CandeoOnOffRemoteCluster,
)
from zhaquirks.const import CLUSTER_ID, COMMAND, ENDPOINT_ID, PARAMS

remote_quirk = (
QuirkBuilder()
.replaces(CandeoOnOffRemoteCluster, endpoint_id=2, cluster_type=ClusterType.Client)
.replaces(
CandeoLevelControlRemoteCluster, endpoint_id=2, cluster_type=ClusterType.Client
)
.device_automation_triggers(
{
("Pressed", "Rotary knob"): {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'll come back to you on this, but I believe we should not have English strings in here. Instead, we should use translation keys (with the translations in ZHA).

Copy link
Contributor

Choose a reason for hiding this comment

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

Hi @TheJulianJES - is this feedback confirmed?
Waiting for your feedback so we can do what's required (if anything). - Thanks

Copy link
Collaborator

Choose a reason for hiding this comment

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

Similar to other device triggers, use something like that here (e.g. see const.py and other quirks). We'll then use that string as the translation key in HA's ZHA integration with a translation there.

So, we'll need to add the trigger strings to HA's ZHA integration here:
https://github.com/home-assistant/core/blob/00955b8e6af26d5a73386a2773a69486e50154dd/homeassistant/components/zha/strings.json#L269-L294

I should be able to do that in the ZHA bump if you provide me with the translations we want to go with.

COMMAND: COMMAND_PRESS,
CLUSTER_ID: 6,
ENDPOINT_ID: 2,
},
("Double pressed", "Rotary knob"): {
COMMAND: COMMAND_DOUBLE_PRESS,
CLUSTER_ID: 6,
ENDPOINT_ID: 2,
},
("Held", "Rotary knob"): {
COMMAND: COMMAND_HOLD,
CLUSTER_ID: 6,
ENDPOINT_ID: 2,
},
("Released", "Rotary knob"): {
COMMAND: COMMAND_RELEASE,
CLUSTER_ID: 6,
ENDPOINT_ID: 2,
},
("Started rotating left", "Rotary knob"): {
COMMAND: COMMAND_STARTED_ROTATING,
CLUSTER_ID: 8,
ENDPOINT_ID: 2,
PARAMS: {"direction": 1},
},
("Rotating left", "Rotary knob"): {
COMMAND: COMMAND_CONTINUED_ROTATING,
CLUSTER_ID: 8,
ENDPOINT_ID: 2,
PARAMS: {"direction": 1},
},
("Started rotating right", "Rotary knob"): {
COMMAND: COMMAND_STARTED_ROTATING,
CLUSTER_ID: 8,
ENDPOINT_ID: 2,
PARAMS: {"direction": 0},
},
("Rotating right", "Rotary knob"): {
COMMAND: COMMAND_CONTINUED_ROTATING,
CLUSTER_ID: 8,
ENDPOINT_ID: 2,
PARAMS: {"direction": 0},
},
("Stopped rotating", "Rotary knob"): {
COMMAND: COMMAND_STOPPED_ROTATING,
CLUSTER_ID: 8,
ENDPOINT_ID: 2,
},
}
)
)

(
QuirkBuilder(CANDEO, "C-ZB-RD1")
.applies_to(CANDEO, "C-ZB-RD1P-DIM")
.removes(Ota.cluster_id)
.add_to_registry()
)

(
remote_quirk.clone()
.applies_to(CANDEO, "C-ZB-RD1P-REM")
.removes(Identify.cluster_id, endpoint_id=1)
.removes(Identify.cluster_id, endpoint_id=2)
.removes(Ota.cluster_id)
.add_to_registry()
)

(
remote_quirk.clone()
.applies_to(CANDEO, "C-ZB-RD1P-DPM")
.removes(Ota.cluster_id)
.add_to_registry()
)
37 changes: 37 additions & 0 deletions zhaquirks/candeo/smart_led_controllers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Candeo smart led controllers."""

from zigpy.quirks.v2 import QuirkBuilder
from zigpy.zcl.clusters.lighting import Color

from zhaquirks.candeo import (
CANDEO,
CandeoCCTColorCluster,
CandeoRGBCCTColorCluster,
CandeoRGBColorCluster,
)

(
QuirkBuilder(CANDEO, "C-ZB-LC20-Dim")
.applies_to(CANDEO, "C-ZB-LC20-DIM")
.removes(Color.cluster_id, endpoint_id=11)
.add_to_registry()
)

(
QuirkBuilder(CANDEO, "C-ZB-LC20-CCT")
.replaces(CandeoCCTColorCluster, endpoint_id=11)
.add_to_registry()
)

(
QuirkBuilder(CANDEO, "C-ZB-LC20-RGB")
.replaces(CandeoRGBColorCluster, endpoint_id=11)
.add_to_registry()
)

(
QuirkBuilder(CANDEO, "C-ZB-LC20-RGBCCT")
.applies_to(CANDEO, "C-ZB-LC20-RGBW")
.replaces(CandeoRGBCCTColorCluster, endpoint_id=11)
.add_to_registry()
)
Loading