Skip to content
Merged
4 changes: 2 additions & 2 deletions tests/data/devices/bitron-video-902010-24a.json
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@
"unique_id": "ab:cd:ef:12:f4:7b:a3:f4-1-1282",
"migrate_unique_ids": [],
"platform": "siren",
"class_name": "Siren",
"class_name": "AdvancedSiren",
"translation_key": null,
"translation_placeholders": null,
"device_class": null,
Expand Down Expand Up @@ -605,7 +605,7 @@
"supported_features": 31
},
"state": {
"class_name": "Siren",
"class_name": "AdvancedSiren",
"available": true,
"state": false
}
Expand Down
4 changes: 2 additions & 2 deletions tests/data/devices/climaxtechnology-sd8sc-00-00-03-12tc.json
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@
"unique_id": "00:12:4b:00:09:6e:5a:cf-1-1282",
"migrate_unique_ids": [],
"platform": "siren",
"class_name": "Siren",
"class_name": "AdvancedSiren",
"translation_key": null,
"translation_placeholders": null,
"device_class": null,
Expand Down Expand Up @@ -582,7 +582,7 @@
"supported_features": 31
},
"state": {
"class_name": "Siren",
"class_name": "AdvancedSiren",
"available": true,
"state": false
}
Expand Down
15 changes: 4 additions & 11 deletions tests/data/devices/frient-a-s-flszb-110.json
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@
"unique_id": "00:15:bc:00:33:00:76:9a-35-1282",
"migrate_unique_ids": [],
"platform": "siren",
"class_name": "Siren",
"class_name": "BasicSiren",
"translation_key": null,
"translation_placeholders": null,
"device_class": null,
Expand Down Expand Up @@ -811,18 +811,11 @@
"endpoint_id": 35,
"available": true,
"group_id": null,
"available_tones": {
"1": "Burglar",
"2": "Fire",
"3": "Emergency",
"4": "Police Panic",
"5": "Fire Panic",
"6": "Emergency Panic"
},
"supported_features": 31
"available_tones": {},
"supported_features": 19
},
"state": {
"class_name": "Siren",
"class_name": "BasicSiren",
"available": true,
"state": false
}
Expand Down
15 changes: 4 additions & 11 deletions tests/data/devices/frient-a-s-scazb-141.json
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,7 @@
"unique_id": "ab:cd:ef:12:18:f2:e7:e6-35-1282",
"migrate_unique_ids": [],
"platform": "siren",
"class_name": "Siren",
"class_name": "BasicSiren",
"translation_key": null,
"translation_placeholders": null,
"device_class": null,
Expand Down Expand Up @@ -1151,18 +1151,11 @@
"endpoint_id": 35,
"available": true,
"group_id": null,
"available_tones": {
"1": "Burglar",
"2": "Fire",
"3": "Emergency",
"4": "Police Panic",
"5": "Fire Panic",
"6": "Emergency Panic"
},
"supported_features": 31
"available_tones": {},
"supported_features": 19
},
"state": {
"class_name": "Siren",
"class_name": "BasicSiren",
"available": true,
"state": false
}
Expand Down
4 changes: 2 additions & 2 deletions tests/data/devices/frient-a-s-sirzb-111.json
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@
"unique_id": "00:15:bc:00:41:00:6f:8e-43",
"migrate_unique_ids": [],
"platform": "siren",
"class_name": "Siren",
"class_name": "AdvancedSiren",
"translation_key": null,
"translation_placeholders": null,
"device_class": null,
Expand Down Expand Up @@ -701,7 +701,7 @@
"supported_features": 31
},
"state": {
"class_name": "Siren",
"class_name": "AdvancedSiren",
"available": true,
"state": false
}
Expand Down
15 changes: 4 additions & 11 deletions tests/data/devices/frient-a-s-smszb-120.json
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@
"unique_id": "00:15:bc:00:31:01:f8:92-35-1282",
"migrate_unique_ids": [],
"platform": "siren",
"class_name": "Siren",
"class_name": "BasicSiren",
"translation_key": null,
"translation_placeholders": null,
"device_class": null,
Expand Down Expand Up @@ -836,18 +836,11 @@
"endpoint_id": 35,
"available": true,
"group_id": null,
"available_tones": {
"1": "Burglar",
"2": "Fire",
"3": "Emergency",
"4": "Police Panic",
"5": "Fire Panic",
"6": "Emergency Panic"
},
"supported_features": 31
"available_tones": {},
"supported_features": 19
},
"state": {
"class_name": "Siren",
"class_name": "BasicSiren",
"available": true,
"state": false
}
Expand Down
4 changes: 2 additions & 2 deletions tests/data/devices/homr-hrmsn01.json
Original file line number Diff line number Diff line change
Expand Up @@ -1127,7 +1127,7 @@
"unique_id": "f4:ce:36:f8:ec:e4:c3:5d-1-1282",
"migrate_unique_ids": [],
"platform": "siren",
"class_name": "Siren",
"class_name": "AdvancedSiren",
"translation_key": null,
"translation_placeholders": null,
"device_class": null,
Expand Down Expand Up @@ -1167,7 +1167,7 @@
"supported_features": 31
},
"state": {
"class_name": "Siren",
"class_name": "AdvancedSiren",
"available": true,
"state": false
}
Expand Down
4 changes: 2 additions & 2 deletions tests/data/devices/tyzb01-8scntis1-ts0216.json
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@
"unique_id": "ab:cd:ef:12:52:26:72:dc-1",
"migrate_unique_ids": [],
"platform": "siren",
"class_name": "Siren",
"class_name": "AdvancedSiren",
"translation_key": null,
"translation_placeholders": null,
"device_class": null,
Expand Down Expand Up @@ -660,7 +660,7 @@
"supported_features": 31
},
"state": {
"class_name": "Siren",
"class_name": "AdvancedSiren",
"available": true,
"state": false
}
Expand Down
78 changes: 78 additions & 0 deletions tests/test_siren.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import asyncio
from unittest.mock import patch

from zhaquirks.quirk_ids import SIREN_BASIC
from zigpy.const import SIG_EP_PROFILE
from zigpy.profiles import zha
from zigpy.zcl.clusters import general, security
Expand All @@ -25,6 +26,7 @@

async def siren_mock(
zha_gateway: Gateway,
basic: bool = False,
) -> tuple[Device, security.IasWd]:
"""Siren fixture."""

Expand All @@ -40,6 +42,9 @@ async def siren_mock(
},
)

if basic:
zigpy_device.quirk_id = {SIREN_BASIC}

zha_device = await join_zigpy_device(zha_gateway, zigpy_device)
return zha_device, zigpy_device.endpoints[1].ias_wd

Expand Down Expand Up @@ -119,6 +124,79 @@ async def test_siren(zha_gateway: Gateway) -> None:
assert entity.state["state"] is True


async def test_basic_siren(zha_gateway: Gateway) -> None:
"""Test zha basic siren."""

zha_device, cluster = await siren_mock(zha_gateway, basic=True)
assert cluster is not None

entity = get_entity(zha_device, platform=Platform.SIREN)
assert entity.supported_features == (
SirenEntityFeature.TURN_ON
| SirenEntityFeature.TURN_OFF
| SirenEntityFeature.DURATION
)

assert entity.state["state"] is False

# turn on from client
with patch(
"zigpy.zcl.Cluster.request",
return_value=[0x00, zcl_f.Status.SUCCESS],
):
await entity.async_turn_on()
await zha_gateway.async_block_till_done()
assert len(cluster.request.mock_calls) == 1
assert cluster.request.call_args[0][0] is False
assert cluster.request.call_args[0][1] == 0
assert cluster.request.call_args[0][3] == 18 # bitmask for default args
assert cluster.request.call_args[0][4] == 5 # duration in seconds
assert cluster.request.call_args[0][5] == 0
assert cluster.request.call_args[0][6] == 2
cluster.request.reset_mock()

# test that the state has changed to on
assert entity.state["state"] is True

# turn off from client
with patch(
"zigpy.zcl.Cluster.request",
return_value=mock_coro([0x00, zcl_f.Status.SUCCESS]),
):
await entity.async_turn_off()
await zha_gateway.async_block_till_done()
assert len(cluster.request.mock_calls) == 1
assert cluster.request.call_args[0][0] is False
assert cluster.request.call_args[0][1] == 0
assert cluster.request.call_args[0][3] == 2 # bitmask for default args
assert cluster.request.call_args[0][4] == 5 # duration in seconds
assert cluster.request.call_args[0][5] == 0
assert cluster.request.call_args[0][6] == 2
cluster.request.reset_mock()

# test that the state has changed to off
assert entity.state["state"] is False

# turn on from client with duration option
with patch(
"zigpy.zcl.Cluster.request",
return_value=mock_coro([0x00, zcl_f.Status.SUCCESS]),
):
await entity.async_turn_on(duration=100)
await zha_gateway.async_block_till_done()
assert len(cluster.request.mock_calls) == 1
assert cluster.request.call_args[0][0] is False
assert cluster.request.call_args[0][1] == 0
assert cluster.request.call_args[0][3] == 18 # bitmask for specified args
assert cluster.request.call_args[0][4] == 100 # duration in seconds
assert cluster.request.call_args[0][5] == 0
assert cluster.request.call_args[0][6] == 2
cluster.request.reset_mock()

# test that the state has changed to on
assert entity.state["state"] is True


async def test_siren_timed_off(zha_gateway: Gateway) -> None:
"""Test zha siren platform."""
zha_device, cluster = await siren_mock(zha_gateway)
Expand Down
3 changes: 3 additions & 0 deletions zha/application/platforms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ class PlatformFeatureGroup(StrEnum):
# Prefer OTA client update entities over OTA server update entities
OTA_UPDATE = "ota_update"

# IAS WD siren entity selection
SIREN = "siren"


@dataclasses.dataclass(frozen=True)
class ClusterHandlerMatch:
Expand Down
Loading
Loading