Skip to content

Commit

Permalink
Merge branch 'release/0.0.53'
Browse files Browse the repository at this point in the history
  • Loading branch information
dmulcahey committed Jan 26, 2021
2 parents 6bd2bcf + 6280d23 commit 93d220d
Show file tree
Hide file tree
Showing 23 changed files with 408 additions and 109 deletions.
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from setuptools import find_packages, setup

VERSION = "0.0.52"
VERSION = "0.0.53"


def readme():
Expand All @@ -24,6 +24,6 @@ def readme():
keywords="zha quirks homeassistant hass",
packages=find_packages(exclude=["tests"]),
python_requires=">=3",
install_requires=["zigpy>=0.28.2"],
install_requires=["zigpy>=0.32.0"],
tests_require=["pytest"],
)
16 changes: 14 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MANUFACTURER,
MODEL,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
Expand Down Expand Up @@ -74,11 +76,17 @@ def _dev(ieee=None, nwk=zigpy.types.NWK(0x1234)):
def zigpy_device_from_quirk(MockAppController, ieee_mock):
"""Create zigpy device from Quirk's signature."""

def _dev(quirk, ieee=None, nwk=zigpy.types.NWK(0x1234)):
def _dev(quirk, ieee=None, nwk=zigpy.types.NWK(0x1234), apply_quirk=True):
if ieee is None:
ieee = ieee_mock
models_info = quirk.signature.get(
MODELS_INFO, (("Mock Manufacturer", "Mock Model"),)
MODELS_INFO,
(
(
quirk.signature.get(MANUFACTURER, "Mock Manufacturer"),
quirk.signature.get(MODEL, "Mock Model"),
),
),
)
manufacturer, model = models_info[0]

Expand All @@ -97,6 +105,10 @@ def _dev(quirk, ieee=None, nwk=zigpy.types.NWK(0x1234)):
out_clusters = ep_data.get(OUTPUT_CLUSTERS, [])
for cluster_id in out_clusters:
ep.add_output_cluster(cluster_id)

if not apply_quirk:
return raw_device

device = quirk(MockAppController, ieee, nwk, raw_device)
MockAppController.devices[ieee] = device

Expand Down
30 changes: 29 additions & 1 deletion tests/test_tuya.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import pytest
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.quirks import CustomDevice, get_device
import zigpy.types as t
from zigpy.zcl import foundation

Expand All @@ -24,6 +24,8 @@
import zhaquirks.tuya.electric_heating
import zhaquirks.tuya.motion
import zhaquirks.tuya.siren
import zhaquirks.tuya.ts0042
import zhaquirks.tuya.ts0043
import zhaquirks.tuya.valve

from tests.common import ClusterListener
Expand Down Expand Up @@ -528,3 +530,29 @@ async def async_success(*args, **kwargs):

status = await thermostat_cluster.command(0x0002)
assert status == foundation.Status.UNSUP_CLUSTER_COMMAND


@pytest.mark.parametrize(
"quirk, manufacturer",
(
(zhaquirks.tuya.ts0042.TuyaSmartRemote0042, "_TZ3000_owgcnkrh"),
(zhaquirks.tuya.ts0042.TuyaSmartRemote0042, "_TZ3400_keyjhapk"),
(zhaquirks.tuya.ts0042.TuyaSmartRemote0042, "_some_random_manuf"),
(zhaquirks.tuya.ts0042.BenexmartRemote0042, "_TZ3000_adkvzooy"),
(zhaquirks.tuya.ts0042.BenexmartRemote0042, "_TZ3400_keyjhapk"),
(zhaquirks.tuya.ts0042.BenexmartRemote0042, "another random manufacturer"),
(zhaquirks.tuya.ts0043.TuyaSmartRemote0043, "_TZ3000_bi6lpsew"),
(zhaquirks.tuya.ts0043.TuyaSmartRemote0043, "_TZ3000_a7ouggvs"),
(zhaquirks.tuya.ts0043.TuyaSmartRemote0043, "another random manufacturer"),
(zhaquirks.tuya.ts0043.BenexmartRemote0043, "_TZ3000_qzjcsmar"),
(zhaquirks.tuya.ts0043.BenexmartRemote0043, "another random manufacturer"),
),
)
async def test_tuya_wildcard_manufacturer(zigpy_device_from_quirk, quirk, manufacturer):
"""Test thermostatic valve outgoing commands."""

zigpy_dev = zigpy_device_from_quirk(quirk, apply_quirk=False)
zigpy_dev.manufacturer = manufacturer

quirked_dev = get_device(zigpy_dev)
assert isinstance(quirked_dev, quirk)
31 changes: 25 additions & 6 deletions zhaquirks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import importlib
import logging
import pkgutil
from typing import Any, Dict, Optional
from typing import Any, Dict, List, Optional, Union

import zigpy.device
import zigpy.endpoint
from zigpy.quirks import CustomCluster, CustomDevice
import zigpy.types as t
from zigpy.util import ListenableMixin
from zigpy.zcl import foundation
from zigpy.zcl.clusters.general import PowerConfiguration
Expand Down Expand Up @@ -101,14 +102,24 @@ async def write_attributes(self, attributes, manufacturer=None):
class EventableCluster(CustomCluster):
"""Cluster that generates events."""

def handle_cluster_request(self, tsn, command_id, args):
def handle_cluster_request(
self,
hdr: foundation.ZCLHeader,
args: List[Any],
*,
dst_addressing: Optional[
Union[t.Addressing.Group, t.Addressing.IEEE, t.Addressing.NWK]
] = None,
):
"""Send cluster requests as events."""
if (
self.server_commands is not None
and self.server_commands.get(command_id) is not None
and self.server_commands.get(hdr.command_id) is not None
):
self.listener_event(
ZHA_SEND_EVENT, self.server_commands.get(command_id)[0], args
ZHA_SEND_EVENT,
self.server_commands.get(hdr.command_id, (hdr.command_id))[0],
args,
)

def _update_attribute(self, attrid, value):
Expand Down Expand Up @@ -235,9 +246,17 @@ class MotionWithReset(_Motion):

send_occupancy_event: bool = False

def handle_cluster_request(self, tsn, command_id, args):
def handle_cluster_request(
self,
hdr: foundation.ZCLHeader,
args: List[Any],
*,
dst_addressing: Optional[
Union[t.Addressing.Group, t.Addressing.IEEE, t.Addressing.NWK]
] = None,
):
"""Handle the cluster command."""
if command_id == ZONE_STATE:
if hdr.command_id == ZONE_STATE:
if self._timer_handle:
self._timer_handle.cancel()
self._timer_handle = self._loop.call_later(self.reset_s, self._turn_off)
Expand Down
1 change: 1 addition & 0 deletions zhaquirks/danfoss/thermostat.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class DanfossThermostatCluster(CustomCluster, Thermostat):
0x4000: ("etrv_open_windows_detection", t.enum8),
0x4003: ("external_open_windows_detected", t.Bool),
0x4014: ("orientation", t.Bool),
0x4015: ("external_measured_room_sensor", t.int16s),
}


Expand Down
14 changes: 11 additions & 3 deletions zhaquirks/ikea/opencloseremote.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""Device handler for IKEA of Sweden TRADFRI remote control."""
from typing import List
from typing import Any, List, Optional, Union

from zigpy.profiles import zha
from zigpy.quirks import CustomCluster, CustomDevice
import zigpy.types as t
from zigpy.zcl import foundation
from zigpy.zcl.clusters.closures import WindowCovering
from zigpy.zcl.clusters.general import (
Alarms,
Expand Down Expand Up @@ -52,14 +54,20 @@ def __init__(self, *args, **kwargs):
self._is_closing = None

def handle_cluster_request(
self, tsn: int, command_id: int, args: List[int]
self,
hdr: foundation.ZCLHeader,
args: List[Any],
*,
dst_addressing: Optional[
Union[t.Addressing.Group, t.Addressing.IEEE, t.Addressing.NWK]
] = None,
) -> None:
"""Handle cluster specific commands.
We just want to keep track of direction, to associate it with the stop command.
"""

cmd_name = self.server_commands.get(command_id, [command_id])[0]
cmd_name = self.server_commands.get(hdr.command_id, [hdr.command_id])[0]
if cmd_name == COMMAND_OPEN:
self._is_closing = False
elif cmd_name == COMMAND_CLOSE:
Expand Down
11 changes: 10 additions & 1 deletion zhaquirks/konke/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Konke sensors."""
from typing import Any, List, Optional, Union

import zigpy.types as t
from zigpy.zcl.clusters.general import OnOff
Expand Down Expand Up @@ -38,7 +39,15 @@ class KonkeOnOffCluster(CustomCluster, OnOff):
ep_attribute = "custom_on_off"
manufacturer_attributes = {0x0000: (PRESS_TYPE, t.uint8_t)}

def handle_cluster_general_request(self, header, args):
def handle_cluster_general_request(
self,
header: zigpy.zcl.foundation.ZCLHeader,
args: List[Any],
*,
dst_addressing: Optional[
Union[t.Addressing.Group, t.Addressing.IEEE, t.Addressing.NWK]
] = None,
):
"""Handle the cluster command."""
self.info(
"Konke general request - handle_cluster_general_request: header: %s - args: [%s]",
Expand Down
18 changes: 14 additions & 4 deletions zhaquirks/philips/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import asyncio
import logging
import time
from typing import Any, List, Optional, Union

from zigpy.quirks import CustomCluster
import zigpy.types as t
from zigpy.zcl import foundation
from zigpy.zcl.clusters.general import Basic, LevelControl, OnOff
from zigpy.zcl.clusters.lighting import Color
from zigpy.zcl.clusters.measurement import OccupancySensing
Expand Down Expand Up @@ -178,12 +180,20 @@ class PhilipsRemoteCluster(CustomCluster):

button_press_queue = ButtonPressQueue()

def handle_cluster_request(self, tsn, command_id, args):
def handle_cluster_request(
self,
hdr: foundation.ZCLHeader,
args: List[Any],
*,
dst_addressing: Optional[
Union[t.Addressing.Group, t.Addressing.IEEE, t.Addressing.NWK]
] = None,
):
"""Handle the cluster command."""
_LOGGER.debug(
"PhilipsRemoteCluster - handle_cluster_request tsn: [%s] command id: %s - args: [%s]",
tsn,
command_id,
hdr.tsn,
hdr.command_id,
args,
)

Expand All @@ -193,7 +203,7 @@ def handle_cluster_request(self, tsn, command_id, args):
event_args = {
BUTTON: button,
PRESS_TYPE: press_type,
COMMAND_ID: command_id,
COMMAND_ID: hdr.command_id,
ARGS: args,
}

Expand Down
14 changes: 13 additions & 1 deletion zhaquirks/philips/zhadimmablelight.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,19 @@ class ZHADimmableLight(CustomDevice):
"""Philips ZigBee HomeAutomation dimmable bulb device."""

signature = {
MODELS_INFO: [(PHILIPS, "LWV001"), (SIGNIFY, "LWV001")],
MODELS_INFO: [
(PHILIPS, "LWA004"),
(PHILIPS, "LWA005"),
(PHILIPS, "LWA007"),
(PHILIPS, "LWO001"),
(PHILIPS, "LWO003"),
(PHILIPS, "LWV001"),
(SIGNIFY, "LWA004"),
(SIGNIFY, "LWA005"),
(SIGNIFY, "LWO001"),
(SIGNIFY, "LWO003"),
(SIGNIFY, "LWV001"),
],
ENDPOINTS: {
11: {
# <SimpleDescriptor endpoint=11 profile=260 device_type=528
Expand Down
36 changes: 36 additions & 0 deletions zhaquirks/samjin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
"""Module for Samjin quirks implementations."""
import logging
from typing import Any, List, Optional, Union

from zigpy.quirks import CustomCluster
from zigpy.types import Addressing
from zigpy.zcl import foundation
import zigpy.zcl.clusters.security

from ..const import ARGS, COMMAND_ID, PRESS_TYPE, ZHA_SEND_EVENT

_LOGGER = logging.getLogger(__name__)

DOUBLE = 2
HOLD = 3
SAMJIN = "Samjin"
SINGLE = 1

CLICK_TYPES = {SINGLE: "single", DOUBLE: "double", HOLD: "hold"}


class SamjinIASCluster(CustomCluster, zigpy.zcl.clusters.security.IasZone):
"""Occupancy cluster."""

def handle_cluster_request(
self,
hdr: foundation.ZCLHeader,
args: List[Any],
*,
dst_addressing: Optional[
Union[Addressing.Group, Addressing.IEEE, Addressing.NWK]
] = None,
):
"""Handle a cluster command received on this cluster."""
if hdr.command_id == 0:
state = args[0] & 3
event_args = {
PRESS_TYPE: CLICK_TYPES[state],
COMMAND_ID: hdr.command_id,
ARGS: args,
}
action = "button_{}".format(CLICK_TYPES[state])
self.listener_event(ZHA_SEND_EVENT, action, event_args)
Loading

0 comments on commit 93d220d

Please sign in to comment.