Skip to content

Instantly share code, notes, and snippets.

@vinzent
Last active June 3, 2024 20:19
Show Gist options
  • Save vinzent/811cb3dda20b559cbb97693c5db03caa to your computer and use it in GitHub Desktop.
Save vinzent/811cb3dda20b559cbb97693c5db03caa to your computer and use it in GitHub Desktop.
"""Luminance motion sensor ZG-Z204ZS"""
import math
from typing import Dict, Final
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import (
Basic,
PowerConfiguration,
Identify,
)
import zigpy.types as t
from zigpy.zcl.clusters.measurement import IlluminanceMeasurement, OccupancySensing
from zigpy.zcl.clusters.security import IasZone
from zigpy.zcl.foundation import ZCLAttributeDef
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster, TuyaPowerConfigurationCluster2AAA
from zhaquirks.tuya.mcu import (
DPToAttributeMapping,
TuyaMCUCluster,
)
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
SKIP_CONFIGURATION,
)
class TuyaOccupancySensing(OccupancySensing, TuyaLocalCluster):
"""Tuya local OccupancySensing cluster."""
class TuyaIlluminanceMeasurement(IlluminanceMeasurement, TuyaLocalCluster):
"""Tuya local IlluminanceMeasurement cluster."""
class SensitivityLevel(t.enum8):
"""Sensitivity level enum."""
LOW = 0x00
MEDIUM = 0x01
HIGH = 0x02
class KeepTime(t.enum8):
"""Keep time"""
_10_SEC = 0x00
_30_SEC = 0x01
_60_SEC = 0x02
_120_SEC = 0x03
class LuminancePresenceSensorCluster(TuyaMCUCluster, NoManufacturerCluster):
"""Tuya Manufacturer cluster"""
class AttributeDefs(TuyaMCUCluster.AttributeDefs):
"""Manufacturer specific attribute definitions"""
sensitivity_level: Final = ZCLAttributeDef(
id=0xEF09, # DP 9
type=SensitivityLevel,
is_manufacturer_specific=True,
)
keep_time: Final = ZCLAttributeDef(
id=0xEF0A, # DP 10
type=KeepTime,
is_manufacturer_specific=True,
)
light_sense_interval: Final = ZCLAttributeDef(
id=0xEF66, # DP 102
type=t.uint16_t,
is_manufacturer_specific=True,
)
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
1: DPToAttributeMapping(
TuyaOccupancySensing.ep_attribute,
"occupancy",
converter=lambda x: IasZone.ZoneStatus.Alarm_1 if not x else 0,
),
4: DPToAttributeMapping(
TuyaPowerConfigurationCluster2AAA.ep_attribute,
"battery_percentage_remaining",
),
9: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"sensitivity_level",
converter=lambda x: SensitivityLevel(x),
),
10: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"keep_time",
converter=lambda x: KeepTime(x),
),
12: DPToAttributeMapping(
TuyaIlluminanceMeasurement.ep_attribute,
"measured_value",
converter=lambda x: 10000 * math.log10(x) + 1 if x != 0 else 0,
),
102: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"light_sense_interval",
),
}
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",
}
class LuminancePresenceSensor(CustomDevice):
"""Tuya Human Presence Sensor"""
signature = {
MODELS_INFO: [("_TZE200_3towulqd", "TS0601")],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
INPUT_CLUSTERS: [
Basic.cluster_id,
PowerConfiguration.cluster_id,
Identify.cluster_id,
IlluminanceMeasurement.cluster_id,
IasZone.cluster_id,
],
OUTPUT_CLUSTERS: []
}
},
}
replacement = {
SKIP_CONFIGURATION: True,
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
TuyaPowerConfigurationCluster2AAA,
LuminancePresenceSensorCluster,
TuyaOccupancySensing,
TuyaIlluminanceMeasurement,
],
OUTPUT_CLUSTERS: [],
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment