Skip to content

Commit

Permalink
Merge branch 'dev' into add-rain-_TZ3210_tgvtvdoc
Browse files Browse the repository at this point in the history
  • Loading branch information
prairiesnpr authored Jan 24, 2025
2 parents 831e444 + d9481d3 commit cbe1574
Show file tree
Hide file tree
Showing 50 changed files with 976 additions and 370 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Stale
# yamllint disable-line rule:truthy
on:
schedule:
- cron: "0 * * * *"
- cron: "30 1 * * *"
workflow_dispatch:

jobs:
Expand All @@ -16,7 +16,7 @@ jobs:
# - No PRs marked as no-stale
# - No issues marked as no-stale or help-wanted
- name: 180 days stale issues & PRs policy
uses: actions/stale@v8
uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 180
Expand Down Expand Up @@ -49,7 +49,7 @@ jobs:
# - No Issues marked as no-stale or help-wanted
# - No PRs (-1)
- name: Needs more information stale issues policy
uses: actions/stale@v8
uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
only-labels: "needs more information"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ZHA Device Handlers For Home Assistant

![CI](https://github.com/zigpy/zha-device-handlers/workflows/CI/badge.svg?branch=dev)
[![CI](https://github.com/zigpy/zha-device-handlers/actions/workflows/ci.yml/badge.svg)](https://github.com/zigpy/zha-device-handlers/actions/workflows/ci.yml)
[![Coverage Status](https://codecov.io/gh/zigpy/zha-device-handlers/branch/dev/graph/badge.svg)](https://app.codecov.io/gh/zigpy/zha-device-handlers/tree/dev)

ZHA Device Handlers are custom quirks implementations for [Zigpy](https://github.com/zigpy/zigpy), the library that provides the [Zigbee](http://www.zigbee.org) support for the [ZHA](https://www.home-assistant.io/components/zha/) component in [Home Assistant](https://www.home-assistant.io).
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ readme = "README.md"
license = {text = "Apache-2.0"}
requires-python = ">=3.12"
dependencies = [
"zigpy>=0.74.0",
"zigpy>=0.75.1",
]

[tool.setuptools.packages.find]
Expand Down
2 changes: 1 addition & 1 deletion requirements_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ pytest-sugar
pytest-timeout
pytest-asyncio
pytest>=7.1.3
zigpy>=0.74.0
zigpy>=0.75.1
ruff==0.0.261
22 changes: 19 additions & 3 deletions tests/test_inovelli_blue.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from unittest import mock
from unittest.mock import MagicMock

import zigpy.types as t

import zhaquirks
from zhaquirks.inovelli.VZM31SN import InovelliVZM31SNv11

Expand All @@ -25,7 +27,15 @@ class Listener:
cluster_listener
)

device.handle_message(260, cluster_id, endpoint_id, endpoint_id, data)
device.packet_received(
t.ZigbeePacket(
profile_id=260,
cluster_id=cluster_id,
src_ep=endpoint_id,
dst_ep=endpoint_id,
data=t.SerializableBytes(data),
)
)

assert cluster_listener.zha_send_event.call_count == 1
assert cluster_listener.zha_send_event.call_args == mock.call(
Expand All @@ -35,8 +45,14 @@ class Listener:
cluster_listener.zha_send_event.reset_mock()

led_effect_complete_data = b"\x15/\x12\x0c$\x10"
device.handle_message(
260, cluster_id, endpoint_id, endpoint_id, led_effect_complete_data
device.packet_received(
t.ZigbeePacket(
profile_id=260,
cluster_id=cluster_id,
src_ep=endpoint_id,
dst_ep=endpoint_id,
data=t.SerializableBytes(led_effect_complete_data),
)
)

assert cluster_listener.zha_send_event.call_count == 1
Expand Down
31 changes: 28 additions & 3 deletions tests/test_konke.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from unittest import mock

import pytest
import zigpy.types as t

from tests.common import ZCL_IAS_MOTION_COMMAND, ClusterListener
import zhaquirks
Expand Down Expand Up @@ -83,7 +84,15 @@ async def test_konke_button(zigpy_device_from_quirk, quirk):

# single press
message = b"\x08W\n\x00\x00\x10\x80"
device.handle_message(260, cluster.cluster_id, 1, 1, message)
device.packet_received(
t.ZigbeePacket(
profile_id=260,
cluster_id=cluster.cluster_id,
src_ep=1,
dst_ep=1,
data=t.SerializableBytes(message),
)
)
assert listener.zha_send_event.call_count == 1
assert listener.zha_send_event.call_args_list[0][0][0] == COMMAND_SINGLE
assert listener.zha_send_event.call_args_list[0][0][1][PRESS_TYPE] == COMMAND_SINGLE
Expand All @@ -92,7 +101,15 @@ async def test_konke_button(zigpy_device_from_quirk, quirk):
# double press
listener.reset_mock()
message = b"\x08X\n\x00\x00\x10\x81"
device.handle_message(260, cluster.cluster_id, 1, 1, message)
device.packet_received(
t.ZigbeePacket(
profile_id=260,
cluster_id=cluster.cluster_id,
src_ep=1,
dst_ep=1,
data=t.SerializableBytes(message),
)
)
assert listener.zha_send_event.call_count == 1
assert listener.zha_send_event.call_args_list[0][0][0] == COMMAND_DOUBLE
assert listener.zha_send_event.call_args_list[0][0][1][PRESS_TYPE] == COMMAND_DOUBLE
Expand All @@ -101,7 +118,15 @@ async def test_konke_button(zigpy_device_from_quirk, quirk):
# long press
listener.reset_mock()
message = b"\x08Y\n\x00\x00\x10\x82"
device.handle_message(260, cluster.cluster_id, 1, 1, message)
device.packet_received(
t.ZigbeePacket(
profile_id=260,
cluster_id=cluster.cluster_id,
src_ep=1,
dst_ep=1,
data=t.SerializableBytes(message),
)
)
assert listener.zha_send_event.call_count == 1
assert listener.zha_send_event.call_args_list[0][0][0] == COMMAND_HOLD
assert listener.zha_send_event.call_args_list[0][0][1][PRESS_TYPE] == COMMAND_HOLD
Expand Down
11 changes: 10 additions & 1 deletion tests/test_linxura.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from unittest import mock

import pytest
import zigpy.types as t
from zigpy.zcl.clusters.security import IasZone

import zhaquirks
Expand Down Expand Up @@ -105,7 +106,15 @@ async def test_button_triggers(zigpy_device_from_quirk, message, button, press_t
listener = mock.MagicMock()
cluster.add_listener(listener)

device.handle_message(260, cluster.cluster_id, 1, 1, message)
device.packet_received(
t.ZigbeePacket(
profile_id=260,
cluster_id=cluster.cluster_id,
src_ep=1,
dst_ep=1,
data=t.SerializableBytes(message),
)
)
assert listener.zha_send_event.call_count == 1
assert listener.zha_send_event.call_args == mock.call(
f"{button}_{press_type}",
Expand Down
2 changes: 1 addition & 1 deletion tests/test_philips.py
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ def test_PhilipsRemoteCluster_long_press(
(4),
),
)
def test_ButtonPressQueue_presses_without_pause(button_presses):
async def test_ButtonPressQueue_presses_without_pause(button_presses):
"""Test ButtonPressQueue presses without pause in between presses."""

q = ButtonPressQueue()
Expand Down
2 changes: 1 addition & 1 deletion tests/test_quirks.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
zhaquirks.setup()

ALL_QUIRK_CLASSES = []
for manufacturer in zq._DEVICE_REGISTRY._registry.values():
for manufacturer in zq.DEVICE_REGISTRY.registry_v1.values():
for model_quirk_list in manufacturer.values():
for quirk in model_quirk_list:
if quirk in ALL_QUIRK_CLASSES:
Expand Down
30 changes: 27 additions & 3 deletions tests/test_quirks_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@

zhaquirks.setup()


ALL_QUIRK_V2_CLASSES: list[QuirksV2RegistryEntry] = itertools.chain.from_iterable(
zigpy.quirks._DEVICE_REGISTRY._registry_v2.values()
# zigpy registry v2 contains duplicates (due to being keyed by manufacturer and model),
# so to avoid duplicates but maintain insertion order, we use a dict instead of a set
ALL_QUIRK_V2_CLASSES: dict[QuirksV2RegistryEntry, None] = dict.fromkeys(
itertools.chain.from_iterable(zigpy.quirks.DEVICE_REGISTRY.registry_v2.values())
)


Expand Down Expand Up @@ -46,3 +47,26 @@ def test_translation_key_and_fallback_name_match() -> None:
assert (
len(set(fallback_names)) == 1
), f"Translation key '{translation_key}' is shared by quirks with different fallback names: {quirk_locations}"


def test_manufacturer_model_metadata_unique() -> None:
"""Ensure that each manufacturer-model pair is unique across all v2 quirks."""
# quirk_locations are a list and not a set below,
# as they are not guaranteed to be unique when set up incorrectly

# (manufacturer, model) -> {quirk_location}
man_model_quirk_map: dict[tuple[str, str], list[str]] = collections.defaultdict(
list
)

for quirk in ALL_QUIRK_V2_CLASSES:
for metadata in quirk.manufacturer_model_metadata:
man_model_quirk_map[(metadata.manufacturer, metadata.model)].append(
f"{quirk.quirk_file}:{quirk.quirk_file_line}"
)

# check that each manufacturer-model pair is unique
for (manufacturer, model), quirk_locations in man_model_quirk_map.items():
assert (
len(quirk_locations) == 1
), f"Manufacturer-model pair '{manufacturer}' '{model}' is shared by multiple quirks: {quirk_locations}"
2 changes: 1 addition & 1 deletion tests/test_tuya.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
import zhaquirks.tuya.ts0601_electric_heating
import zhaquirks.tuya.ts0601_motion
import zhaquirks.tuya.ts0601_trv
import zhaquirks.tuya.ts0601_valve
import zhaquirks.tuya.ts601_door
import zhaquirks.tuya.ts1201
import zhaquirks.tuya.tuya_valve

zhaquirks.setup()

Expand Down
21 changes: 17 additions & 4 deletions tests/test_tuya_air.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import pytest
import zigpy.profiles.zha
import zigpy.types as t

import zhaquirks
from zhaquirks.tuya import TuyaNewManufCluster
Expand Down Expand Up @@ -65,8 +66,14 @@ def air_quality_device(zigpy_device_from_v2_quirk):
def test_co2_sensor(air_quality_device, data, ep_attr, expected_value):
"""Test Tuya Air Quality Sensor."""

air_quality_device.handle_message(
zigpy.profiles.zha.PROFILE_ID, TuyaNewManufCluster.cluster_id, 1, 1, data
air_quality_device.packet_received(
t.ZigbeePacket(
profile_id=zigpy.profiles.zha.PROFILE_ID,
cluster_id=TuyaNewManufCluster.cluster_id,
src_ep=1,
dst_ep=1,
data=t.SerializableBytes(data),
)
)
cluster = getattr(air_quality_device.endpoints[1], ep_attr)
assert cluster.get("measured_value") == expected_value
Expand Down Expand Up @@ -132,8 +139,14 @@ def smart_air_quality_device(zigpy_device_from_v2_quirk):
def test_smart_air_sensor(smart_air_quality_device, data, ep_attr, expected_value):
"""Test Tuya Smart Air Sensor."""

smart_air_quality_device.handle_message(
zigpy.profiles.zha.PROFILE_ID, TuyaNewManufCluster.cluster_id, 1, 1, data
smart_air_quality_device.packet_received(
t.ZigbeePacket(
profile_id=zigpy.profiles.zha.PROFILE_ID,
cluster_id=TuyaNewManufCluster.cluster_id,
src_ep=1,
dst_ep=1,
data=t.SerializableBytes(data),
)
)
cluster = getattr(smart_air_quality_device.endpoints[1], ep_attr)
assert cluster.get("measured_value") == expected_value
Loading

0 comments on commit cbe1574

Please sign in to comment.