Skip to content

Commit

Permalink
Merge branch 'dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
pulsar895 authored Nov 4, 2024
2 parents 5407e92 + 728ee42 commit 804024a
Show file tree
Hide file tree
Showing 13 changed files with 267 additions and 71 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ repos:
args: ["--toml", "pyproject.toml"]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.11.2
rev: v1.13.0
hooks:
- id: mypy

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.9
rev: v0.7.1
hooks:
- id: ruff
args: ["--fix", "--exit-non-zero-on-fix", "--config", "pyproject.toml"]
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 License Version 2.0"}
requires-python = ">=3.12"
dependencies = [
"zigpy>=0.68.1",
"zigpy>=0.70.0",
]

[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.69
zigpy>=0.70
ruff==0.0.261
62 changes: 49 additions & 13 deletions tests/test_sinope.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@

from tests.common import ClusterListener
import zhaquirks
from zhaquirks.const import COMMAND_BUTTON_DOUBLE, COMMAND_BUTTON_HOLD
from zhaquirks.const import (
COMMAND_M_INITIAL_PRESS,
COMMAND_M_LONG_RELEASE,
COMMAND_M_MULTI_PRESS_COMPLETE,
COMMAND_M_SHORT_RELEASE,
TURN_OFF,
TURN_ON,
)
from zhaquirks.sinope import SINOPE_MANUFACTURER_CLUSTER_ID
from zhaquirks.sinope.light import (
SinopeTechnologieslight,
Expand Down Expand Up @@ -92,20 +99,22 @@ def _get_packet_data(

@pytest.mark.parametrize("quirk", (SinopeTechnologieslight,))
@pytest.mark.parametrize(
"press_type,exp_event",
"press_type,button,exp_event",
(
(ButtonAction.Single_off, None),
(ButtonAction.Single_on, None),
(ButtonAction.Double_on, COMMAND_BUTTON_DOUBLE),
(ButtonAction.Double_off, COMMAND_BUTTON_DOUBLE),
(ButtonAction.Long_on, COMMAND_BUTTON_HOLD),
(ButtonAction.Long_off, COMMAND_BUTTON_HOLD),
(ButtonAction.Pressed_off, TURN_OFF, COMMAND_M_INITIAL_PRESS),
(ButtonAction.Pressed_on, TURN_ON, COMMAND_M_INITIAL_PRESS),
(ButtonAction.Released_off, TURN_OFF, COMMAND_M_SHORT_RELEASE),
(ButtonAction.Released_on, TURN_ON, COMMAND_M_SHORT_RELEASE),
(ButtonAction.Double_on, TURN_ON, COMMAND_M_MULTI_PRESS_COMPLETE),
(ButtonAction.Double_off, TURN_OFF, COMMAND_M_MULTI_PRESS_COMPLETE),
(ButtonAction.Long_on, TURN_ON, COMMAND_M_LONG_RELEASE),
(ButtonAction.Long_off, TURN_OFF, COMMAND_M_LONG_RELEASE),
# Should gracefully handle broken actions.
(t.uint8_t(0x00), None),
(t.uint8_t(0x00), None, None),
),
)
async def test_sinope_light_switch(
zigpy_device_from_quirk, quirk, press_type, exp_event
zigpy_device_from_quirk, quirk, press_type, button, exp_event
):
"""Test that button presses are sent as events."""
device: Device = zigpy_device_from_quirk(quirk)
Expand All @@ -126,7 +135,16 @@ class Listener:
),
)
data = _get_packet_data(foundation.GeneralCommand.Report_Attributes, attr)
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),
)
)

if exp_event is None:
assert cluster_listener.zha_send_event.call_count == 0
Expand All @@ -137,6 +155,8 @@ class Listener:
{
"attribute_id": 84,
"attribute_name": "action_report",
"button": button,
"description": press_type.name,
"value": press_type.value,
},
)
Expand All @@ -162,7 +182,15 @@ class Listener:

# read attributes general command
data = _get_packet_data(foundation.GeneralCommand.Read_Attributes)
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),
)
)
# no ZHA events emitted because we only handle Report_Attributes
assert cluster_listener.zha_send_event.call_count == 0

Expand All @@ -174,7 +202,15 @@ class Listener:
), # 0x29 = t.int16s
)
data = _get_packet_data(foundation.GeneralCommand.Report_Attributes, attr)
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),
)
)
# ZHA event emitted because we pass non "action_report"
# reports to the base class handler.
assert cluster_listener.zha_send_event.call_count == 1
Expand Down
10 changes: 10 additions & 0 deletions tests/test_tuya_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,35 @@ class TestEnum(t.enum8):
.tuya_switch(
dp_id=6,
attribute_name="test_onoff",
translation_key="test_onoff",
fallback_name="Test on/off",
)
.tuya_number(
dp_id=7,
attribute_name="test_number",
type=t.uint16_t,
translation_key="test_number",
fallback_name="Test number",
)
.tuya_binary_sensor(
dp_id=8,
attribute_name="test_binary",
translation_key="test_binary",
fallback_name="Test binary",
)
.tuya_sensor(
dp_id=9,
attribute_name="test_sensor",
type=t.uint8_t,
translation_key="test_sensor",
fallback_name="Test sensor",
)
.tuya_enum(
dp_id=10,
attribute_name="test_enum",
enum_class=TestEnum,
translation_key="test_enum",
fallback_name="Test enum",
)
.tuya_humidity(dp_id=11)
.add_to_registry()
Expand Down
22 changes: 20 additions & 2 deletions zhaquirks/lixee/zlinky.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Identify,
Ota,
PowerConfiguration,
Time,
)
from zigpy.zcl.clusters.homeautomation import ElectricalMeasurement, MeterIdentification
from zigpy.zcl.clusters.smartenergy import Metering
Expand All @@ -24,6 +25,7 @@
PROFILE_ID,
)
from zhaquirks.lixee import LIXEE, ZLINKY_MANUFACTURER_CLUSTER_ID
from zhaquirks.tuya import TuyaManufCluster


class ZLinkyTICManufacturerCluster(CustomCluster):
Expand Down Expand Up @@ -200,9 +202,25 @@ class ZLinkyTIC(CustomDevice):


class ZLinkyTICFWV12(ZLinkyTIC):
"""ZLinky_TIC from LiXee with firmware v12.0+."""
"""ZLinky_TIC from LiXee with firmware v12.0 & v13.0."""

signature = deepcopy(ZLinkyTIC.signature)

# Insert PowerConfiguration cluster in signature for devices with firmware v12.0+
# Insert PowerConfiguration cluster in signature for devices with firmware v12.0 & v13.0
signature[ENDPOINTS][1][INPUT_CLUSTERS].insert(1, PowerConfiguration.cluster_id)


class ZLinkyTICFWV14(ZLinkyTICFWV12):
"""ZLinky_TIC from LiXee with firmware v14.0+."""

signature = deepcopy(ZLinkyTICFWV12.signature)
replacement = deepcopy(ZLinkyTICFWV12.replacement)

# Insert Time configuration cluster in signature for devices with firmware v14.0+
signature[ENDPOINTS][1][INPUT_CLUSTERS].insert(1, Time.cluster_id)

# Insert Tuya cluster in signature for devices with firmware v14.0+
signature[ENDPOINTS][1][INPUT_CLUSTERS].insert(7, TuyaManufCluster.cluster_id)
signature[ENDPOINTS][1][OUTPUT_CLUSTERS].insert(1, TuyaManufCluster.cluster_id)

replacement[ENDPOINTS][1][INPUT_CLUSTERS].insert(1, Time.cluster_id)
3 changes: 3 additions & 0 deletions zhaquirks/nimly/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Nimly module."""

NIMLY = "Onesti Products AS"
43 changes: 43 additions & 0 deletions zhaquirks/nimly/lock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Device handler for Nimly Smart Locks."""

from zigpy.quirks.v2 import QuirkBuilder
from zigpy.zdo.types import NodeDescriptor

from zhaquirks import DoublingPowerConfigurationCluster
from zhaquirks.nimly import NIMLY

# clears the mains powered mac capability flag
NIMLY_LOCK_NODE_DESCRIPTOR = NodeDescriptor(
logical_type=2,
complex_descriptor_available=0,
user_descriptor_available=0,
reserved=0,
aps_flags=0,
frequency_band=8,
manufacturer_code=4660,
maximum_buffer_size=108,
maximum_incoming_transfer_size=127,
server_mask=11264,
maximum_outgoing_transfer_size=127,
descriptor_capability_field=0,
mac_capability_flags=NodeDescriptor.MACCapabilityFlags.AllocateAddress
| NodeDescriptor.MACCapabilityFlags.RxOnWhenIdle,
)


(
QuirkBuilder(NIMLY, "EasyFingerTouch")
.also_applies_to(NIMLY, "EasyCodeTouch")
.node_descriptor(NIMLY_LOCK_NODE_DESCRIPTOR)
.add_to_registry()
)

(
QuirkBuilder(NIMLY, "NimlyPRO")
.also_applies_to(NIMLY, "NimlyCode")
.also_applies_to(NIMLY, "NimlyTouch")
.also_applies_to(NIMLY, "NimlyIn")
.node_descriptor(NIMLY_LOCK_NODE_DESCRIPTOR)
.replaces(DoublingPowerConfigurationCluster, endpoint_id=11)
.add_to_registry()
)
6 changes: 2 additions & 4 deletions zhaquirks/philips/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,9 @@ class AttributeDefs(Basic.AttributeDefs):

attr_config = {AttributeDefs.philips.id: 0x000B}

async def bind(self):
"""Bind cluster."""
result = await super().bind()
async def apply_custom_configuration(self, *args, **kwargs):
"""Apply custom configuration."""
await self.write_attributes(self.attr_config, manufacturer=0x100B)
return result


class ButtonPressQueue:
Expand Down
1 change: 0 additions & 1 deletion zhaquirks/philips/soc001.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ class AttributeDefs(BaseAttributeDefs):
endpoint_id=2,
device_class=BinarySensorDeviceClass.TAMPER,
entity_type=EntityType.DIAGNOSTIC,
translation_key="tamper",
fallback_name="Tamper",
)
.add_to_registry()
Expand Down
Loading

0 comments on commit 804024a

Please sign in to comment.