Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions tests/test_tuya_motion.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
ZCL_TUYA_MOTION_V6 = b"\tL\x01\x00\x05\x01\x04\x00\x01\x02" # DP 1, enum
ZCL_TUYA_MOTION_V7 = b"\tL\x01\x00\x05\x01\x01\x00\x01\x00" # DP 1, Inv
ZCL_TUYA_MOTION_V8 = b"\tL\x01\x00\x05\x65\x01\x00\x01\x00" # DP 101, Inv
ZCL_TUYA_MOTION_V9 = b"\tL\x01\x00\x05\x68\x01\x00\x01\x01" # DP 104


zhaquirks.setup()
Expand Down Expand Up @@ -67,6 +68,7 @@
("_TZE200_2aaelwxk", "TS0601", ZCL_TUYA_MOTION),
("_TZE200_kb5noeto", "TS0601", ZCL_TUYA_MOTION),
("_TZE204_ex3rcdha", "TS0601", ZCL_TUYA_MOTION_V8),
("_TZE204_gkfbdvyx", "TS0601", ZCL_TUYA_MOTION_V9),
],
)
async def test_tuya_motion_quirk_occ(zigpy_device_from_v2_quirk, model, manuf, occ_msg):
Expand Down
118 changes: 117 additions & 1 deletion zhaquirks/tuya/tuya_motion.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ class TuyaPresenceStateV02(t.enum8):
Gigantic = 0x05


class TuyaPresenceStateV03(t.enum8):
"""Tuya presence state enum, variation 03."""

Unoccupied = 0x00
Presence = 0x01
Movement = 0x02


class TuyaBreakerMode(t.enum8):
"""Tuya breaker mode enum."""

Expand Down Expand Up @@ -236,7 +244,6 @@ class TuyaMotionDetectionMode(t.enum8):

(
base_tuya_motion.clone()
.applies_to("_TZE200_gkfbdvyx", "TS0601")
.applies_to("_TZE200_ya4ft0w4", "TS0601")
.applies_to("_TZE204_ya4ft0w4", "TS0601")
.tuya_dp(
Expand Down Expand Up @@ -1611,3 +1618,112 @@ class TuyaMotionDetectionMode(t.enum8):
.skip_configuration()
.add_to_registry()
)


# Tuya mmWave radar 24GHz, _TZE204_gkfbdvyx
# Loginovo Smart Human Presence Sensor M100, Model C3007
# TZ-HS-24G / ZY-M100-24G / Ceiling Human Breathe Sensor 24G
(
TuyaQuirkBuilder("_TZE204_gkfbdvyx", "TS0601")
.applies_to("_TZE200_gkfbdvyx", "TS0601")
# 0: presence="none", state=false
# 1: presence="presence" state=true triggers only with presence sensitivity on low
# 2: presence="move" state=true
.tuya_enum(
dp_id=1,
attribute_name="presence",
enum_class=TuyaPresenceStateV03,
entity_platform=EntityPlatform.SENSOR,
entity_type=EntityType.STANDARD,
translation_key="presence_state",
fallback_name="Presence state",
)
.tuya_dp(
dp_id=104,
ep_attribute=TuyaOccupancySensing.ep_attribute,
attribute_name=OccupancySensing.AttributeDefs.occupancy.name,
converter=lambda x: x == 1,
)
.adds(TuyaOccupancySensing)
.tuya_number(
dp_id=2,
attribute_name="motion_sensitivity",
type=t.uint16_t,
min_value=1,
max_value=10,
step=1,
translation_key="motion_sensitivity",
fallback_name="Motion sensitivity",
)
.tuya_number(
dp_id=3,
attribute_name="detection_distance_min",
type=t.uint16_t,
multiplier=0.01,
device_class=SensorDeviceClass.DISTANCE,
unit=UnitOfLength.METERS,
min_value=0,
max_value=6,
step=0.5,
translation_key="detection_distance_min",
fallback_name="Minimum range",
)
.tuya_number(
dp_id=4,
attribute_name="detection_distance_max",
type=t.uint16_t,
multiplier=0.01,
device_class=SensorDeviceClass.DISTANCE,
unit=UnitOfLength.METERS,
min_value=0.5,
max_value=9, # tested on 6m
step=0.5,
translation_key="detection_distance_max",
fallback_name="Maximum range",
)
.tuya_sensor(
dp_id=9,
attribute_name="distance",
type=t.uint16_t,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.DISTANCE,
unit=UnitOfLength.METERS,
multiplier=0.1,
entity_type=EntityType.STANDARD,
translation_key="target_distance",
fallback_name="Target distance",
)
Comment on lines +1648 to +1695
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would it make sense to clone base_tuya_motion.clone() for DP IDs 2, 3, 4, and 9? Or are the values too different? The values for base_tuya_motion for reference:

base_tuya_motion = (
TuyaQuirkBuilder()
.adds(TuyaOccupancySensing)
.tuya_number(
dp_id=2,
attribute_name="move_sensitivity",
type=t.uint16_t,
min_value=0,
max_value=10,
step=1,
translation_key="move_sensitivity",
fallback_name="Motion sensitivity",
)
.tuya_number(
dp_id=3,
attribute_name="detection_distance_min",
type=t.uint16_t,
device_class=SensorDeviceClass.DISTANCE,
unit=UnitOfLength.METERS,
min_value=0,
max_value=8.25,
step=0.75,
multiplier=0.01,
translation_key="detection_distance_min",
fallback_name="Minimum range",
)
.tuya_number(
dp_id=4,
attribute_name="detection_distance_max",
type=t.uint16_t,
device_class=SensorDeviceClass.DISTANCE,
unit=UnitOfLength.METERS,
min_value=0.75,
max_value=9.0,
step=0.75,
multiplier=0.01,
translation_key="detection_distance_max",
fallback_name="Maximum range",
)
.tuya_sensor(
dp_id=9,
attribute_name="distance",
type=t.uint16_t,
divisor=100,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.DISTANCE,
unit=UnitOfLength.METERS,
entity_type=EntityType.STANDARD,
translation_key="distance",
fallback_name="Target distance",
)
.skip_configuration()
)

Copy link
Author

Choose a reason for hiding this comment

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

This sensor model (i have two) does not like sensitivity set to 0, it seems to crash and stops responding until it is reset and paired again. i don't know how much the different steps and values do to the sensor or if they work at all in between values but this allegedly what the Tuya app says for this sensor.

My best guess is to not copy the base and i don't see a reason to do it unless it can be verified that it is actually working correctly with those numbers. In the long run with more sensors with different capabilites coming all the time, it is not better for readability or code maintenance to continue to use that base.

.tuya_switch(
# Turns distance reporting on and off
dp_id=101,
attribute_name="distance_tracking",
entity_type=EntityType.CONFIG,
translation_key="distance_tracking",
fallback_name="Distance tracking",
)
.tuya_number(
dp_id=102,
attribute_name="presence_sensitivity",
type=t.uint16_t,
min_value=1,
max_value=10,
step=1,
translation_key="presence_sensitivity",
fallback_name="Presence sensitivity",
)
.tuya_illuminance(dp_id=103)
.tuya_number(
dp_id=105,
attribute_name="fading_time",
type=t.uint16_t,
device_class=SensorDeviceClass.DURATION,
unit=UnitOfTime.SECONDS,
min_value=5,
max_value=15000,
step=5,
translation_key="fading_time",
fallback_name="Fading time",
)
.skip_configuration()
.add_to_registry()
)
Loading