-
Notifications
You must be signed in to change notification settings - Fork 723
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
45 changed files
with
2,275 additions
and
1,005 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
name: Stale | ||
|
||
# yamllint disable-line rule:truthy | ||
on: | ||
schedule: | ||
- cron: "0 * * * *" | ||
workflow_dispatch: | ||
|
||
jobs: | ||
stale: | ||
runs-on: ubuntu-latest | ||
steps: | ||
# The 180 day stale policy | ||
# Used for: | ||
# - Issues & PRs | ||
# - 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@v4 | ||
with: | ||
repo-token: ${{ secrets.GITHUB_TOKEN }} | ||
days-before-stale: 180 | ||
days-before-close: 7 | ||
operations-per-run: 150 | ||
remove-stale-when-updated: true | ||
stale-issue-label: "stale" | ||
exempt-issue-labels: "no-stale,help-wanted" | ||
stale-issue-message: > | ||
There hasn't been any activity on this issue recently. Due to the | ||
high number of incoming GitHub notifications, we have to clean some | ||
of the old issues, as many of them have already been resolved with | ||
the latest updates. | ||
Please make sure to update to the latest version and check if that | ||
solves the issue. Let us know if that works for you by adding a | ||
comment 👍 | ||
This issue has now been marked as stale and will be closed if no | ||
further activity occurs. Thank you for your contributions. | ||
stale-pr-label: "stale" | ||
exempt-pr-labels: "no-stale" | ||
stale-pr-message: > | ||
There hasn't been any activity on this pull request recently. This | ||
pull request has been automatically marked as stale because of that | ||
and will be closed if no further activity occurs within 7 days. | ||
Thank you for your contributions. | ||
# The 60 day stale policy for issues | ||
# Used for: | ||
# - Issues that are pending more information (incomplete issues) | ||
# - No Issues marked as no-stale or help-wanted | ||
# - No PRs (-1) | ||
- name: Needs more information stale issues policy | ||
uses: actions/stale@v4 | ||
with: | ||
repo-token: ${{ secrets.GITHUB_TOKEN }} | ||
only-labels: "needs-more-information" | ||
days-before-stale: 60 | ||
days-before-close: 7 | ||
days-before-pr-close: -1 | ||
operations-per-run: 50 | ||
remove-stale-when-updated: true | ||
stale-issue-label: "stale" | ||
exempt-issue-labels: "no-stale,help-wanted" | ||
stale-issue-message: > | ||
There hasn't been any activity on this issue recently. Due to the | ||
high number of incoming GitHub notifications, we have to clean some | ||
of the old issues, as many of them have already been resolved with | ||
the latest updates. | ||
Please make sure to update to the latest version and check if that | ||
solves the issue. Let us know if that works for you by adding a | ||
comment 👍 | ||
This issue has now been marked as stale and will be closed if no | ||
further activity occurs. Thank you for your contributions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
|
||
from setuptools import find_packages, setup | ||
|
||
VERSION = "0.0.57" | ||
VERSION = "0.0.60" | ||
|
||
|
||
def readme(): | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
"""Test Tuya Air quality sensor.""" | ||
|
||
from unittest import mock | ||
|
||
import pytest | ||
import zigpy.profiles.zha | ||
|
||
import zhaquirks | ||
from zhaquirks.tuya import TuyaNewManufCluster | ||
from zhaquirks.tuya.air.ts0601_air_quality import TuyaCO2Sensor | ||
|
||
zhaquirks.setup() | ||
|
||
|
||
@pytest.fixture | ||
def air_quality_device(zigpy_device_from_quirk): | ||
"""Tuya Air Quality Sensor.""" | ||
dev = zigpy_device_from_quirk(TuyaCO2Sensor) | ||
cluster = dev.endpoints[1].in_clusters[TuyaNewManufCluster.cluster_id] | ||
with mock.patch.object(cluster, "send_default_rsp"): | ||
yield dev | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"data, ep_attr, expected_value", | ||
( | ||
( | ||
b"\t2\x01\x00\x02\x02\x02\x00\x04\x00\x00\x01r", | ||
"carbon_dioxide_concentration", | ||
370 * 1e-6, | ||
), | ||
( | ||
b"\t$\x01\x00\x00\x13\x02\x00\x04\x00\x00\x02\xd6", | ||
"humidity", | ||
7260, | ||
), | ||
( | ||
b"\t\x03\x01\x00\x01\x15\x02\x00\x04\x00\x00\x00\x01", | ||
"voc_level", | ||
1 * 1e-6, | ||
), | ||
( | ||
b"\t\x02\x01\x00\x01\x16\x02\x00\x04\x00\x00\x00\x02", | ||
"formaldehyde_concentration", | ||
2 * 1e-6, | ||
), | ||
( | ||
b"\t\x02\x01\x00\x00\x12\x02\x00\x04\x00\x00\x01 ", | ||
"temperature", | ||
2880, | ||
), | ||
), | ||
) | ||
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 | ||
) | ||
cluster = getattr(air_quality_device.endpoints[1], ep_attr) | ||
assert cluster.get("measured_value") == expected_value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
"""Test units for new Tuya cluster framework.""" | ||
|
||
from unittest import mock | ||
|
||
import pytest | ||
import zigpy.zcl.foundation as zcl_f | ||
|
||
from zhaquirks.tuya import ( | ||
TUYA_ACTIVE_STATUS_RPT, | ||
TUYA_GET_DATA, | ||
TUYA_SET_DATA_RESPONSE, | ||
TUYA_SET_TIME, | ||
TuyaCommand, | ||
TuyaData, | ||
TuyaNewManufCluster, | ||
) | ||
|
||
|
||
@pytest.fixture(name="TuyaCluster") | ||
def tuya_cluster(zigpy_device_mock): | ||
"""Mock of the new Tuya manufacturer cluster.""" | ||
device = zigpy_device_mock() | ||
endpoint = device.add_endpoint(1) | ||
cluster = TuyaNewManufCluster(endpoint) | ||
return cluster | ||
|
||
|
||
def test_tuya_data_value(): | ||
"""Test tuya "Value" datatype.""" | ||
|
||
data = b"\x02\x00\x04\x00\x00\x02\xdb" | ||
extra = b"extra data" | ||
|
||
r, rest = TuyaData.deserialize(data + extra) | ||
assert rest == extra | ||
|
||
assert r.dp_type == 2 | ||
assert r.raw == b"\xdb\x02\x00\x00" | ||
assert r.payload == 731 | ||
|
||
|
||
def test_tuya_data_bool(): | ||
"""Test tuya Bool datatype.""" | ||
|
||
data = b"\x01\x00\x01\x00" | ||
extra = b"extra data" | ||
|
||
r, rest = TuyaData.deserialize(data + extra) | ||
assert rest == extra | ||
|
||
assert r.dp_type == 1 | ||
assert r.raw == b"\x00" | ||
assert not r.payload | ||
|
||
data = b"\x01\x00\x01\x01" | ||
extra = b"extra data" | ||
|
||
r, rest = TuyaData.deserialize(data + extra) | ||
assert rest == extra | ||
|
||
assert r.dp_type == 1 | ||
assert r.raw == b"\x01" | ||
assert r.payload | ||
|
||
|
||
def test_tuya_data_enum(): | ||
"""Test tuya Enum datatype.""" | ||
|
||
data = b"\x04\x00\x01\x40" | ||
extra = b"extra data" | ||
|
||
r, rest = TuyaData.deserialize(data + extra) | ||
assert rest == extra | ||
|
||
assert r.dp_type == 4 | ||
assert r.raw == b"\x40" | ||
assert r.payload == 0x40 | ||
|
||
|
||
def test_tuya_data_string(): | ||
"""Test tuya String datatype.""" | ||
|
||
data = b"\x03\x00\x04Tuya" | ||
extra = b"extra data" | ||
|
||
r, rest = TuyaData.deserialize(data + extra) | ||
assert rest == extra | ||
|
||
assert r.dp_type == 3 | ||
assert r.raw == b"Tuya" | ||
assert r.payload == "Tuya" | ||
|
||
|
||
def test_tuya_data_bitmap(): | ||
"""Test tuya Bitmap datatype.""" | ||
|
||
data = b"\x05\x00\x01\x40" | ||
extra = b"extra data" | ||
|
||
r, rest = TuyaData.deserialize(data + extra) | ||
assert rest == extra | ||
|
||
assert r.dp_type == 5 | ||
assert r.raw == b"\x40" | ||
assert r.payload == 0x40 | ||
|
||
data = b"\x05\x00\x02\x40\x02" | ||
r, _ = TuyaData.deserialize(data) | ||
r.payload == 0x4002 | ||
|
||
data = b"\x05\x00\x04\x40\x02\x80\x01" | ||
r, _ = TuyaData.deserialize(data) | ||
r.payload == 0x40028001 | ||
|
||
|
||
def test_tuya_data_bitmap_invalid(): | ||
"""Test tuya Bitmap datatype.""" | ||
|
||
data = b"\x05\x00\x03\x4012" | ||
extra = b"extra data" | ||
|
||
r, rest = TuyaData.deserialize(data + extra) | ||
assert rest == extra | ||
|
||
with pytest.raises(ValueError): | ||
r.payload | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"cmd_id, handler_name, args", | ||
( | ||
( | ||
TUYA_GET_DATA, | ||
"handle_get_data", | ||
(TuyaCommand(0, 2, 2, TuyaData(1, 0, b"\x01\x01")),), | ||
), | ||
( | ||
TUYA_SET_DATA_RESPONSE, | ||
"handle_set_data_response", | ||
(TuyaCommand(0, 2, 2, TuyaData(1, 0, b"\x01\x01")),), | ||
), | ||
( | ||
TUYA_ACTIVE_STATUS_RPT, | ||
"handle_active_status_report", | ||
(TuyaCommand(0, 2, 2, TuyaData(1, 0, b"\x01\x01")),), | ||
), | ||
(TUYA_SET_TIME, "handle_set_time_request", (0x1234,)), | ||
), | ||
) | ||
@mock.patch("zhaquirks.tuya.TuyaNewManufCluster.send_default_rsp") | ||
def test_tuya_cluster_request( | ||
default_rsp_mock, cmd_id, handler_name, args, TuyaCluster | ||
): | ||
"""Test cluster specific request.""" | ||
|
||
hdr = zcl_f.ZCLHeader.general(1, cmd_id, is_reply=True) | ||
hdr.frame_control.disable_default_response = False | ||
|
||
with mock.patch.object(TuyaCluster, handler_name) as handler: | ||
handler.return_value = mock.sentinel.status | ||
TuyaCluster.handle_cluster_request(hdr, args) | ||
assert handler.call_count == 1 | ||
assert default_rsp_mock.call_count == 1 | ||
assert default_rsp_mock.call_args[1]["status"] is mock.sentinel.status | ||
|
||
|
||
@mock.patch("zhaquirks.tuya.TuyaNewManufCluster.send_default_rsp") | ||
def test_tuya_cluster_request_unk_command(default_rsp_mock, TuyaCluster): | ||
"""Test cluster specific request handler -- no handler.""" | ||
|
||
hdr = zcl_f.ZCLHeader.general(1, 0xFE, is_reply=True) | ||
hdr.frame_control.disable_default_response = False | ||
|
||
TuyaCluster.handle_cluster_request(hdr, (mock.sentinel.args,)) | ||
assert default_rsp_mock.call_count == 1 | ||
assert default_rsp_mock.call_args[1]["status"] == zcl_f.Status.UNSUP_CLUSTER_COMMAND | ||
|
||
|
||
@mock.patch("zhaquirks.tuya.TuyaNewManufCluster.send_default_rsp") | ||
def test_tuya_cluster_request_no_handler(default_rsp_mock, TuyaCluster): | ||
"""Test cluster specific request handler -- no handler.""" | ||
|
||
hdr = zcl_f.ZCLHeader.general(1, 0xFE, is_reply=True) | ||
hdr.frame_control.disable_default_response = False | ||
|
||
TuyaCluster.client_commands[0xFE] = ("no_such_handler", (), True) | ||
TuyaCluster.handle_cluster_request(hdr, (mock.sentinel.args,)) | ||
assert default_rsp_mock.call_count == 1 | ||
assert default_rsp_mock.call_args[1]["status"] == zcl_f.Status.UNSUP_CLUSTER_COMMAND |
Oops, something went wrong.