diff --git a/zigpy_zigate/__init__.py b/zigpy_zigate/__init__.py index 5131efb..7e03696 100644 --- a/zigpy_zigate/__init__.py +++ b/zigpy_zigate/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 MINOR_VERSION = 10 -PATCH_VERSION = '0' +PATCH_VERSION = '1' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) diff --git a/zigpy_zigate/types.py b/zigpy_zigate/types.py index 2a94f2f..a92f6cb 100644 --- a/zigpy_zigate/types.py +++ b/zigpy_zigate/types.py @@ -207,6 +207,52 @@ class Status(uint8_t, enum.Enum): # No free BTR entries left. NoFreeBTREntries = 0x8B + # A transmit request failed since the ASDU is too large and fragmentation is not + # supported. + AsduTooLong = 0xA0 + # A received fragmented frame could not be defragmented at the current time. + DefragDeferred = 0xA1 + # A received fragmented frame could not be defragmented since the device does not + # support fragmentation. + DefragUnsupported = 0xA2 + # A parameter value was out of range. + IllegalRequest = 0xA3 + # An APSME-UNBIND.request failed due to the requested binding link not existing in + # the binding table. + InvalidBinding = 0xA4 + # An APSME-REMOVE-GROUP.request has been issued with a group identifier that does + # not appear in the group table. + InvalidGroup = 0xA5 + # A parameter value was invalid or out of range. + InvalidParameter = 0xA6 + # An APSDE-DATA.request requesting acknowledged transmission failed due to no + # acknowledgement being received. + NoAck = 0xA7 + # An APSDE-DATA.request with a destination addressing mode set to 0x00 failed due to + # there being no devices bound to this device. + NoBoundDevice = 0xA8 + # An APSDE-DATA.request with a destination addressing mode set to 0x03 failed due to + # no corresponding short address found in the address map table. + NoShortAddress = 0xA9 + # An APSDE-DATA.request with a destination addressing mode set to 0x00 failed due to + # a binding table not being supported on the device. + NotSupported = 0xAA + # An ASDU was received that was secured using a link key. + SecuredLinkKey = 0xAB + # An ASDU was received that was secured using a network key. + SecuredNwkKey = 0xAC + # An APSDE-DATA.request requesting security has resulted in an error during the + # corresponding security processing. + SecurityFail = 0xAD + # An APSME-BIND.request or APSME.ADDGROUP.request issued when the binding or group + # tables, respectively, were full. + TableFull = 0xAE + # An ASDU was received without any security. + Unsecured = 0xAF + # An APSME-GET.request or APSMESET. request has been issued with an unknown + # attribute identifier. + UnsupportedAttribute = 0xB0 + @classmethod def _missing_(cls, value): if not isinstance(value, int): diff --git a/zigpy_zigate/zigbee/application.py b/zigpy_zigate/zigbee/application.py index c19c477..a903b2b 100644 --- a/zigpy_zigate/zigbee/application.py +++ b/zigpy_zigate/zigbee/application.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import asyncio import logging from typing import Any, Dict, Optional @@ -32,7 +34,7 @@ def __init__(self, config: Dict[str, Any]): self._pending = {} self._pending_join = [] - self.version = '' + self.version: str = "" async def connect(self): api = await ZiGate.new(self._config[CONF_DEVICE], self) @@ -40,12 +42,13 @@ async def connect(self): await api.set_time() version, lqi = await api.version() - hex_version = f"{version[1]:x}" - self.version = f"{hex_version[0]}.{hex_version[1:]}" self._api = api + major, minor = version.to_bytes(2, "big") + self.version = f"{major:x}.{minor:x}" + if self.version < '3.21': - LOGGER.warning('Old ZiGate firmware detected, you should upgrade to 3.21 or newer') + LOGGER.error('Old ZiGate firmware detected, you should upgrade to 3.21 or newer') async def disconnect(self): # TODO: how do you stop the network? Is it possible? @@ -235,20 +238,6 @@ def _handle_frame_failure(self, message_tag, status): async def send_packet(self, packet): LOGGER.debug("Sending packet %r", packet) - if packet.dst.addr_mode == zigpy.types.AddrMode.IEEE: - LOGGER.warning("IEEE addressing is not supported, falling back to NWK") - - try: - device = self.get_device_with_address(packet.dst) - except (KeyError, ValueError): - raise ValueError(f"Cannot find device with IEEE {packet.dst.address}") - - packet = packet.replace( - dst=zigpy.types.AddrModeAddress( - addr_mode=zigpy.types.AddrMode.NWK, address=device.nwk - ) - ) - ack = (zigpy.types.TransmitOptions.ACK in packet.tx_options) try: @@ -265,11 +254,16 @@ async def send_packet(self, packet): except NoResponseError: raise zigpy.exceptions.DeliveryError("ZiGate did not respond to command") + self._pending[tsn] = asyncio.get_running_loop().create_future() + if status != t.Status.Success: self._pending.pop(tsn) - raise zigpy.exceptions.DeliveryError(f"Failed to deliver packet: {status}", status=status) - self._pending[tsn] = asyncio.get_running_loop().create_future() + # Firmwares 3.1d and below fail to send packets on every request + if status == t.Status.InvalidParameter and self.version <= "3.1d": + pass + else: + raise zigpy.exceptions.DeliveryError(f"Failed to send packet: {status}", status=status) # disabled because of https://github.com/fairecasoimeme/ZiGate/issues/324 # try: @@ -300,7 +294,7 @@ def __init__(self, application, ieee, nwk): model = 'PiZiGate' elif c.is_zigate_din(port): model = 'ZiGate USB-DIN' - self._model = '{} {}'.format(model, application.version) + self._model = f'{model} {application.version}' @property def manufacturer(self):