Skip to content

Instantly share code, notes, and snippets.

@vinzent
Last active June 7, 2024 14:24
Show Gist options
  • Save vinzent/2194a8ef531d8e8ec3bc17ea17eab0e9 to your computer and use it in GitHub Desktop.
Save vinzent/2194a8ef531d8e8ec3bc17ea17eab0e9 to your computer and use it in GitHub Desktop.
zg-204zs.py
"""Luminance motion sensor ZG-204ZS"""
from typing import Dict, Final
from zigpy.quirks.v2 import add_to_registry_v2
import zigpy.types as t
from zigpy.zcl.clusters.measurement import IlluminanceMeasurement, OccupancySensing
from zigpy.zcl.clusters.security import IasZone
from zigpy.zcl.clusters.general import Identify
from zigpy.zcl.foundation import ZCLAttributeDef
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster, TuyaPowerConfigurationCluster2AAA
from zhaquirks.tuya.mcu import (
DPToAttributeMapping,
TuyaMCUCluster,
)
class TuyaOccupancySensing(OccupancySensing, TuyaLocalCluster):
"""Tuya local OccupancySensing cluster."""
class TuyaIlluminanceMeasurement(IlluminanceMeasurement, TuyaLocalCluster):
"""Tuya local IlluminanceMeasurement cluster."""
class PirState(t.enum8):
"""Pir state"""
pir = 0x00
none = 0x01
@staticmethod
def to_occupancy(x):
""" Map PIR state to occupancy enum. Actually the PirState is Occupancy inverted."""
if x == PirState.pir:
return OccupancySensing.Occupancy.Occupied
return OccupancySensing.Occupancy.Unoccupied
class PirSensitivity(t.enum8):
"""Sensitivity level enum."""
LOW = 0x00
MEDIUM = 0x01
HIGH = 0x02
class PirTime(t.enum8):
"""Keep time"""
_10_SEC = 0x00
_30_SEC = 0x01
_60_SEC = 0x02
_120_SEC = 0x03
class LuminanceMotionManufCluster(NoManufacturerCluster, TuyaMCUCluster):
"""Tuya Manufacturer cluster"""
# 1 "PIR state" pir_state Enum pir|none
# 4 "Battery level" battery_percentage Integer unit=%,min=0,max=100,scale=0,step=1
# 9 "PIR Sensitivity" pir_sensitivity Enum low|middle|high
# 10 "Keep time" pir_time Enum 10s|30s|60s|120s
# 12 "Illuminance value" illuminance_value Integer unit=lux,min=0,max=10000,scale=0,step=1
# 102 "Light Sense Interval Time(Version 2.0.1 and above)" interval_time Integer unit="Min",min=1,max=720,scale=0,step=1
class AttributeDefs(TuyaMCUCluster.AttributeDefs):
"""Manufacturer specific attribute definitions"""
# Mapped to OccupancySensing cluster
# pir_state: Final = ZCLAttributeDef(
# id=0x0001, # DP 9
# type=PirState,
# is_manufacturer_specific=True,
# )
battery_percentage: Final = ZCLAttributeDef(
id=0x0004, # DP 4
type=t.uint16_t,
is_manufacturer_specific=True,
)
pir_sensitivity: Final = ZCLAttributeDef(
id=0x0009, # DP 9
type=PirSensitivity,
is_manufacturer_specific=True,
)
pir_time: Final = ZCLAttributeDef(
id=0x0010, # DP 10
type=PirTime,
is_manufacturer_specific=True,
)
illuminance_value: Final = ZCLAttributeDef(
id=0x0012, # DP 12
type=t.uint16_t,
is_manufacturer_specific=True,
)
interval_time: Final = ZCLAttributeDef(
id=0x0102, # DP 102
type=t.uint16_t,
is_manufacturer_specific=True,
)
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
1: DPToAttributeMapping(
TuyaOccupancySensing.ep_attribute,
"occupancy",
converter=PirState.to_occupancy
),
4: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"battery_percentage",
),
9: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"pir_sensitivity",
converter=PirSensitivity
),
10: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"pir_time",
converter=PirTime
),
12: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"illuminance_value",
),
102: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"interval_time",
),
}
data_point_handlers = {
1: "_dp_2_attr_update",
4: "_dp_2_attr_update",
9: "_dp_2_attr_update",
10: "_dp_2_attr_update",
12: "_dp_2_attr_update",
102: "_dp_2_attr_update",
}
(
add_to_registry_v2("_TZE200_3towulqd", "TS0601")
.skip_configuration()
.removes(IasZone.cluster_id)
.removes(Identify.cluster_id)
.adds(LuminanceMotionManufCluster)
.adds(TuyaOccupancySensing)
.replaces(TuyaPowerConfigurationCluster2AAA)
.replaces(TuyaIlluminanceMeasurement)
.enum(LuminanceMotionManufCluster.AttributeDefs.pir_time.name, PirTime, LuminanceMotionManufCluster.cluster_id)
.enum(LuminanceMotionManufCluster.AttributeDefs.pir_sensitivity.name,PirSensitivity,LuminanceMotionManufCluster.cluster_id)
# Exception with unit="m" seen with HA 2024.6.0 + 2024.5.x
.number(LuminanceMotionManufCluster.AttributeDefs.interval_time.name,LuminanceMotionManufCluster.cluster_id,step=1,min_value=1,max_value=720)
)
@vinzent
Copy link
Author

vinzent commented Jun 7, 2024

With HA 2024.6.0:

grafik

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment