358 lines
12 KiB
Python
358 lines
12 KiB
Python
# rivsc https://blog.rivsc.ovh
|
|
import logging
|
|
from typing import Final
|
|
|
|
from zigpy.quirks.v2 import QuirkBuilder, BinarySensorDeviceClass
|
|
|
|
import zigpy.types as t
|
|
from zigpy.zcl.foundation import ZCLAttributeDef
|
|
from zigpy.zcl.clusters.measurement import (
|
|
IlluminanceMeasurement,
|
|
OccupancySensing,
|
|
)
|
|
from zigpy.zcl.clusters.security import IasZone
|
|
from zigpy.quirks.v2.homeassistant import EntityPlatform, EntityType
|
|
|
|
from zhaquirks.tuya import (
|
|
TuyaLocalCluster,
|
|
TuyaPowerConfigurationCluster2AAA,
|
|
)
|
|
from zhaquirks.tuya.mcu import TuyaMCUCluster, DPToAttributeMapping
|
|
|
|
class PresenceState(t.enum8):
|
|
"""Presence State values"""
|
|
none = 0x00
|
|
presence = 0x01
|
|
peaceful = 0x02
|
|
small_movement = 0x03
|
|
large_movement = 0x04
|
|
|
|
class TuyaOccupancySensing(OccupancySensing, TuyaLocalCluster):
|
|
"""Tuya local OccupancySensing cluster."""
|
|
|
|
class TuyaIlluminanceMeasurement(IlluminanceMeasurement, TuyaLocalCluster):
|
|
"""Tuya local IlluminanceMeasurement cluster."""
|
|
|
|
class HumanPresenceSensorManufCluster(TuyaMCUCluster):
|
|
"""Human Presence Sensor ZG-205Z (5.8GHz)"""
|
|
|
|
class AttributeDefs(TuyaMCUCluster.AttributeDefs):
|
|
"""Tuya DataPoints attributes"""
|
|
|
|
# Presence state
|
|
presence_state: Final = ZCLAttributeDef(
|
|
id=0x0001, # DP 1
|
|
type=t.uint16_t,
|
|
access="rp",
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Target distance
|
|
target_distance: Final = ZCLAttributeDef(
|
|
id=0x0101, # DP 101
|
|
type=t.uint16_t,
|
|
access="rp",
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Illuminance value
|
|
illuminance_lux: Final = ZCLAttributeDef(
|
|
id=0x0102, # DP 102
|
|
type=t.uint16_t,
|
|
access="rp",
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# None delay time (presence keep time)
|
|
none_delay_time: Final = ZCLAttributeDef(
|
|
id=0x0103, # DP 103
|
|
type=t.uint16_t,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Indicator
|
|
indicator: Final = ZCLAttributeDef(
|
|
id=0x0104, # DP 104
|
|
type=t.Bool,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Move detection max distance
|
|
move_detection_max: Final = ZCLAttributeDef(
|
|
id=0x0107, # DP 107
|
|
type=t.uint16_t,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Move detection min distance
|
|
move_detection_min: Final = ZCLAttributeDef(
|
|
id=0x0108, # DP 108
|
|
type=t.uint16_t,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Breath detection max distance
|
|
breath_detection_max: Final = ZCLAttributeDef(
|
|
id=0x0109, # DP 109
|
|
type=t.uint16_t,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Breath detection min distance
|
|
breath_detection_min: Final = ZCLAttributeDef(
|
|
id=0x0110, # DP 110
|
|
type=t.uint16_t,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Small move detection max distance
|
|
small_move_detection_max: Final = ZCLAttributeDef(
|
|
id=0x0114, # DP 114
|
|
type=t.uint16_t,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Small move detection min distance
|
|
small_move_detection_min: Final = ZCLAttributeDef(
|
|
id=0x0115, # DP 115
|
|
type=t.uint16_t,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Move sensitivity
|
|
move_sensitivity: Final = ZCLAttributeDef(
|
|
id=0x0116, # DP 116
|
|
type=t.uint8_t,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Small move sensitivity
|
|
small_move_sensitivity: Final = ZCLAttributeDef(
|
|
id=0x0117, # DP 117
|
|
type=t.uint8_t,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
# Breath sensitivity
|
|
breath_sensitivity: Final = ZCLAttributeDef(
|
|
id=0x0118, # DP 118
|
|
type=t.uint8_t,
|
|
is_manufacturer_specific=True,
|
|
)
|
|
|
|
dp_to_attribute: dict[int, DPToAttributeMapping] = {
|
|
1: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"presence_state",
|
|
converter=PresenceState
|
|
),
|
|
101: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"target_distance",
|
|
converter=lambda x: x / 100 if x is not None else 0
|
|
),
|
|
102: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"illuminance_lux",
|
|
),
|
|
103: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"none_delay_time",
|
|
converter=lambda x: x if x is not None else 30
|
|
),
|
|
104: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"indicator",
|
|
),
|
|
107: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"move_detection_max",
|
|
converter=lambda x: x / 100 if x is not None else 10
|
|
),
|
|
108: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"move_detection_min",
|
|
converter=lambda x: x / 100 if x is not None else 0
|
|
),
|
|
109: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"breath_detection_max",
|
|
converter=lambda x: x / 100 if x is not None else 6
|
|
),
|
|
110: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"breath_detection_min",
|
|
converter=lambda x: x / 100 if x is not None else 0
|
|
),
|
|
114: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"small_move_detection_max",
|
|
converter=lambda x: x / 100 if x is not None else 6
|
|
),
|
|
115: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"small_move_detection_min",
|
|
converter=lambda x: x / 100 if x is not None else 0
|
|
),
|
|
116: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"move_sensitivity",
|
|
converter=lambda x: x if x is not None else 5
|
|
),
|
|
117: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"small_move_sensitivity",
|
|
converter=lambda x: x if x is not None else 5
|
|
),
|
|
118: DPToAttributeMapping(
|
|
TuyaMCUCluster.ep_attribute,
|
|
"breath_sensitivity",
|
|
converter=lambda x: x if x is not None else 5
|
|
),
|
|
}
|
|
|
|
data_point_handlers = {
|
|
1: "_dp_2_attr_update",
|
|
101: "_dp_2_attr_update",
|
|
102: "_dp_2_attr_update",
|
|
103: "_dp_2_attr_update",
|
|
104: "_dp_2_attr_update",
|
|
107: "_dp_2_attr_update",
|
|
108: "_dp_2_attr_update",
|
|
109: "_dp_2_attr_update",
|
|
110: "_dp_2_attr_update",
|
|
114: "_dp_2_attr_update",
|
|
115: "_dp_2_attr_update",
|
|
116: "_dp_2_attr_update",
|
|
117: "_dp_2_attr_update",
|
|
118: "_dp_2_attr_update",
|
|
}
|
|
|
|
(
|
|
QuirkBuilder("_TZE204_dapwryy7", "TS0601")
|
|
.skip_configuration()
|
|
.removes(IasZone.cluster_id)
|
|
.adds(HumanPresenceSensorManufCluster)
|
|
#.adds(TuyaOccupancySensing)
|
|
.replaces(TuyaPowerConfigurationCluster2AAA)
|
|
.replaces(TuyaIlluminanceMeasurement)
|
|
.binary_sensor(
|
|
"presence_state",
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
endpoint_id=1,
|
|
#entity_type=EntityType.STANDARD, # very soon (zigpy channel #dev on github
|
|
device_class=BinarySensorDeviceClass.OCCUPANCY,
|
|
fallback_name="Presence"
|
|
)
|
|
.enum(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.presence_state.name,
|
|
PresenceState,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
entity_platform=EntityPlatform.SENSOR,
|
|
entity_type=EntityType.STANDARD,
|
|
fallback_name="Presence State",
|
|
translation_key="presence_state"
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.target_distance.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=0.01,
|
|
min_value=0,
|
|
max_value=10,
|
|
#unit="m", # fail :/
|
|
fallback_name="Target Distance (m)",
|
|
translation_key="target_distance",
|
|
#entity_type=EntityType.STANDARD # not yet :/
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.none_delay_time.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=1,
|
|
min_value=0,
|
|
max_value=28800,
|
|
unit="s",
|
|
fallback_name="Hold Delay Time",
|
|
translation_key="none_delay_time"
|
|
)
|
|
.switch(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.indicator.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
fallback_name="LED Indicator",
|
|
translation_key="indicator"
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.move_detection_max.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=0.01,
|
|
min_value=0,
|
|
max_value=10,
|
|
#unit="m",
|
|
fallback_name="Move Detection Max Distance (m)",
|
|
translation_key="move_detection_max"
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.move_detection_min.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=0.01,
|
|
min_value=0,
|
|
max_value=10,
|
|
#unit="m",
|
|
fallback_name="Move Detection Min Distance (m)",
|
|
translation_key="move_detection_min"
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.small_move_detection_max.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=0.01,
|
|
min_value=0,
|
|
max_value=6,
|
|
#unit="m",
|
|
fallback_name="Small Move Detection Max Distance (m)",
|
|
translation_key="small_move_detection_max"
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.small_move_detection_min.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=0.01,
|
|
min_value=0,
|
|
max_value=6,
|
|
#unit="m",
|
|
fallback_name="Small Move Detection Min Distance (m)",
|
|
translation_key="small_move_detection_min"
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.breath_detection_max.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=0.01,
|
|
min_value=0,
|
|
max_value=6,
|
|
#unit="m",
|
|
fallback_name="Breath Detection Max Distance (m)",
|
|
translation_key="breath_detection_max"
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.breath_detection_min.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=0.01,
|
|
min_value=0,
|
|
max_value=6,
|
|
#unit="m",
|
|
fallback_name="Breath Detection Min Distance (m)",
|
|
translation_key="breath_detection_min"
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.move_sensitivity.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=1,
|
|
min_value=0,
|
|
max_value=10,
|
|
fallback_name="Move Sensitivity",
|
|
translation_key="move_sensitivity"
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.small_move_sensitivity.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=1,
|
|
min_value=0,
|
|
max_value=10,
|
|
fallback_name="Small Move Sensitivity",
|
|
translation_key="small_move_sensitivity"
|
|
)
|
|
.number(
|
|
HumanPresenceSensorManufCluster.AttributeDefs.breath_sensitivity.name,
|
|
HumanPresenceSensorManufCluster.cluster_id,
|
|
step=1,
|
|
min_value=0,
|
|
max_value=10,
|
|
fallback_name="Breath Sensitivity",
|
|
translation_key="breath_sensitivity"
|
|
)
|
|
.add_to_registry()
|
|
) |