From 0f6016c30a08bea7dc810bd90c3dfda5545576de Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 15 May 2019 22:03:45 -0400 Subject: [PATCH 01/86] 0.3.4.dev0 -> 0.4.0b0 --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index a61c593e7..ac6997dd1 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 3 -PATCH_VERSION = '4.dev0' +MINOR_VERSION = 4 +PATCH_VERSION = '0b0' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) From ad56b2b01d59d9547e83193f43aa16e71c2d687b Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 15 May 2019 22:04:53 -0400 Subject: [PATCH 02/86] 0.4.0 Version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index ac6997dd1..6bfa3c455 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 4 -PATCH_VERSION = '0b0' +PATCH_VERSION = '0' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) From 75a2f7f4ae449a6ffb6d302eb79a4d7234753de7 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 21 May 2019 09:47:28 -0400 Subject: [PATCH 03/86] Fix float type (Single/Double) deserialization. (#164) * Fix float type deserialization. * Refactor float types. Raise if buffer size is incorrect. --- tests/test_types.py | 20 ++++++++++++++++---- zigpy/types/basic.py | 17 +++++++++-------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/tests/test_types.py b/tests/test_types.py index f2260adaf..faecb82fe 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -13,15 +13,27 @@ def test_int_too_short(): def test_single(): - v = t.Single(1.25) + value = 1.25 + extra = b'ab12!' + v = t.Single(value) ser = v.serialize() - assert t.Single.deserialize(ser) == (1.25, b'') + assert t.Single.deserialize(ser) == (value, b'') + assert t.Single.deserialize(ser + extra) == (value, extra) + + with pytest.raises(ValueError): + t.Double.deserialize(ser[1:]) def test_double(): - v = t.Double(1.25) + value = 1.25 + extra = b'ab12!' + v = t.Double(value) ser = v.serialize() - assert t.Double.deserialize(ser) == (1.25, b'') + assert t.Double.deserialize(ser) == (value, b'') + assert t.Double.deserialize(ser + extra) == (value, extra) + + with pytest.raises(ValueError): + t.Double.deserialize(ser[1:]) def test_lvbytes(): diff --git a/zigpy/types/basic.py b/zigpy/types/basic.py index e64358bdf..187e2cdf8 100644 --- a/zigpy/types/basic.py +++ b/zigpy/types/basic.py @@ -125,21 +125,22 @@ class bitmap64(uint64_t): # noqa: N801 class Single(float): + _fmt = ' Date: Tue, 21 May 2019 20:15:08 -0400 Subject: [PATCH 04/86] Fix ConfigureReportingResponseRecord and WriteAttributeResponseRecord serialization/deserialization. (#161) * zigpy.types.Struct instance init. Initialize zigpy.types.Struct fields during instantiation. * Fix WriteAttributeResponseRecord deserialization. Per ZCL spec r20 section 2.5.5.1.2, WriteAttributeStatusRecord with the Status field set to SUCCESS, the attribute identifier field is ommited. * Fix ConfigureReportingResponse deserialization. Per ZCL spec r20 section 2.5.8.1.3, AttributeStatusRecords with the Status field set to SUCCESS, the directiona and attribute identifier fields are ommited. --- tests/test_types.py | 20 +++++++++++ tests/test_zcl_foundation.py | 70 ++++++++++++++++++++++++++++++++++++ zigpy/types/struct.py | 6 ++++ zigpy/zcl/foundation.py | 48 ++++++++++++++++++++++++- 4 files changed, 143 insertions(+), 1 deletion(-) diff --git a/tests/test_types.py b/tests/test_types.py index faecb82fe..7a52f7e9b 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -179,6 +179,8 @@ class TestStruct(t.Struct): _fields = [('a', t.uint8_t), ('b', t.uint8_t)] ts = TestStruct() + assert ts.a is None + assert ts.b is None ts.a = t.uint8_t(0xaa) ts.b = t.uint8_t(0xbb) ts2 = TestStruct(ts) @@ -193,6 +195,24 @@ class TestStruct(t.Struct): assert s == b'\xaa\xbb' +def test_struct_init(): + class TestStruct(t.Struct): + _fields = [ + ('a', t.uint8_t), + ('b', t.uint16_t), + ('c', t.CharacterString), + ] + + ts = TestStruct(1, 0x0100, 'TestStruct') + assert repr(ts) + assert isinstance(ts.a, t.uint8_t) + assert isinstance(ts.b, t.uint16_t) + assert isinstance(ts.c, t.CharacterString) + assert ts.a == 1 + assert ts.b == 0x100 + assert ts.c == 'TestStruct' + + def test_hex_repr(): class NwkAsHex(t.HexRepr, t.uint16_t): _hex_len = 4 diff --git a/tests/test_zcl_foundation.py b/tests/test_zcl_foundation.py index 7e9d30b97..921d45368 100644 --- a/tests/test_zcl_foundation.py +++ b/tests/test_zcl_foundation.py @@ -80,3 +80,73 @@ def test_typed_collection(): assert tc2.type == 0x20 assert tc2.value == list(range(100)) + + +def test_write_attribute_status_record(): + attr_id = b'\x01\x00' + extra = b'12da-' + res, d = foundation.WriteAttributesStatusRecord.deserialize( + b'\x00' + attr_id + extra) + assert res.status == foundation.Status.SUCCESS + assert res.attrid is None + assert d == attr_id + extra + r = repr(res) + assert r.startswith( + '<' + foundation.WriteAttributesStatusRecord.__name__) + assert 'status' in r + assert 'attrid' not in r + + res, d = foundation.WriteAttributesStatusRecord.deserialize( + b'\x87' + attr_id + extra) + assert res.status == foundation.Status.INVALID_VALUE + assert res.attrid == 0x0001 + assert d == extra + + r = repr(res) + assert 'status' in r + assert 'attrid' in r + + rec = foundation.WriteAttributesStatusRecord( + foundation.Status.SUCCESS, 0xaabb + ) + assert rec.serialize() == b'\x00' + rec.status = foundation.Status.UNSUPPORTED_ATTRIBUTE + assert rec.serialize()[0:1] == foundation.Status.UNSUPPORTED_ATTRIBUTE.serialize() + assert rec.serialize()[1:] == b'\xbb\xaa' + + +def test_configure_reporting_response_serialization(): + direction_attr_id = b'\x00\x01\x10' + extra = b'12da-' + res, d = foundation.ConfigureReportingResponseRecord.deserialize( + b'\x00' + direction_attr_id + extra) + assert res.status == foundation.Status.SUCCESS + assert res.direction is None + assert res.attrid is None + assert d == direction_attr_id + extra + r = repr(res) + assert r.startswith( + '<' + foundation.ConfigureReportingResponseRecord.__name__) + assert 'status' in r + assert 'direction' not in r + assert 'attrid' not in r + + res, d = foundation.ConfigureReportingResponseRecord.deserialize( + b'\x8c' + direction_attr_id + extra) + assert res.status == foundation.Status.UNREPORTABLE_ATTRIBUTE + assert res.direction is not None + assert res.attrid == 0x1001 + assert d == extra + + r = repr(res) + assert 'status' in r + assert 'direction' in r + assert 'attrid' in r + + rec = foundation.ConfigureReportingResponseRecord( + foundation.Status.SUCCESS, 0x00, 0xaabb + ) + assert rec.serialize() == b'\x00' + rec.status = foundation.Status.UNREPORTABLE_ATTRIBUTE + assert rec.serialize()[0:1] == foundation.Status.UNREPORTABLE_ATTRIBUTE.serialize() + assert rec.serialize()[1:] == b'\x00\xbb\xaa' diff --git a/zigpy/types/struct.py b/zigpy/types/struct.py index 00d18d09e..3051d752f 100644 --- a/zigpy/types/struct.py +++ b/zigpy/types/struct.py @@ -4,6 +4,12 @@ def __init__(self, *args, **kwargs): # copy constructor for field in self._fields: setattr(self, field[0], getattr(args[0], field[0])) + elif len(args) == len(self._fields): + for field, value in zip(self._fields, args): + setattr(self, field[0], field[1](value)) + elif not args: + for field in self._fields: + setattr(self, field[0], None) def serialize(self): r = b'' diff --git a/zigpy/zcl/foundation.py b/zigpy/zcl/foundation.py index 584d38bf1..e8fb9020c 100644 --- a/zigpy/zcl/foundation.py +++ b/zigpy/zcl/foundation.py @@ -187,6 +187,28 @@ class WriteAttributesStatusRecord(t.Struct): ('attrid', t.uint16_t), ] + @classmethod + def deserialize(cls, data): + r = cls() + r.status, data = Status.deserialize(data) + if r.status != Status.SUCCESS: + r.attrid, data = t.uint16_t.deserialize(data) + + return r, data + + def serialize(self): + r = Status(self.status).serialize() + if self.status != Status.SUCCESS: + r += t.uint16_t(self.attrid).serialize() + return r + + def __repr__(self): + r = '<%s status=%s' % (self.__class__.__name__, self.status, ) + if self.status != Status.SUCCESS: + r += ' attrid=%s' % (self.attrid, ) + r += '>' + return r + class AttributeReportingConfig: def serialize(self): @@ -228,11 +250,35 @@ def deserialize(cls, data): class ConfigureReportingResponseRecord(t.Struct): _fields = [ - ('status', t.uint8_t), + ('status', Status), ('direction', t.uint8_t), ('attrid', t.uint16_t), ] + @classmethod + def deserialize(cls, data): + r = cls() + r.status, data = Status.deserialize(data) + if r.status != Status.SUCCESS: + r.direction, data = t.uint8_t.deserialize(data) + r.attrid, data = t.uint16_t.deserialize(data) + + return r, data + + def serialize(self): + r = Status(self.status).serialize() + if self.status != Status.SUCCESS: + r += t.uint8_t(self.direction).serialize() + r += t.uint16_t(self.attrid).serialize() + return r + + def __repr__(self): + r = '<%s status=%s' % (self.__class__.__name__, self.status, ) + if self.status != Status.SUCCESS: + r += ' direction=%s attrid=%s' % (self.direction, self.attrid, ) + r += '>' + return r + class ReadReportingConfigRecord(t.Struct): _fields = [ From dd17e23387b2c22bbb5efc03eafbd268ee736747 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 23 May 2019 10:56:55 -0400 Subject: [PATCH 05/86] Allow "Optional" parameters for Commands/Responses schema. (#160) * class Optional -- marks a schema param as optional. Essentially allows deseririalization for this param to raise ValueError, in which case it just returns None as deserialization result. * Update ZDO responses schema. Update schemas for ZDO responses which may have optional params. * Update general clusters with "optional" params. * Update LightLink cluster with "optional" params. * Allow optional parameters for ZCL requests. --- tests/test_types.py | 10 +++++++++ tests/test_zcl.py | 31 +++++++++++++++++++++++++++ zigpy/types/basic.py | 14 +++++++++++++ zigpy/zcl/__init__.py | 3 ++- zigpy/zcl/clusters/general.py | 37 +++++++++++++++++++++++---------- zigpy/zcl/clusters/lightlink.py | 6 ++++-- zigpy/zdo/types.py | 25 +++++++++++++++------- 7 files changed, 104 insertions(+), 22 deletions(-) diff --git a/tests/test_types.py b/tests/test_types.py index 7a52f7e9b..e46de04e7 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -219,3 +219,13 @@ class NwkAsHex(t.HexRepr, t.uint16_t): nwk = NwkAsHex(0x1234) assert str(nwk) == '0x1234' assert repr(nwk) == '0x1234' + + +def test_optional(): + d, r = t.Optional(t.uint8_t).deserialize(b'') + assert d is None + assert r == b'' + + d, r = t.Optional(t.uint8_t).deserialize(b'\x001234aaa') + assert d == 0 + assert r == b'1234aaa' diff --git a/tests/test_zcl.py b/tests/test_zcl.py index 2a9941d34..014ef61a1 100644 --- a/tests/test_zcl.py +++ b/tests/test_zcl.py @@ -102,6 +102,37 @@ def test_request_manufacturer(cluster): assert org_size + 2 == len(cluster._endpoint.request.call_args[0][2]) +def test_request_optional(cluster): + schema = [t.uint8_t, t.uint16_t, t.Optional(t.uint16_t), t.Optional(t.uint8_t)] + + res = cluster.request(True, 0, schema) + assert type(res.exception()) == ValueError + assert cluster._endpoint.request.call_count == 0 + cluster._endpoint.request.reset_mock() + + res = cluster.request(True, 0, schema, 1) + assert type(res.exception()) == ValueError + assert cluster._endpoint.request.call_count == 0 + cluster._endpoint.request.reset_mock() + + cluster.request(True, 0, schema, 1, 2) + assert cluster._endpoint.request.call_count == 1 + cluster._endpoint.request.reset_mock() + + cluster.request(True, 0, schema, 1, 2, 3) + assert cluster._endpoint.request.call_count == 1 + cluster._endpoint.request.reset_mock() + + cluster.request(True, 0, schema, 1, 2, 3, 4) + assert cluster._endpoint.request.call_count == 1 + cluster._endpoint.request.reset_mock() + + res = cluster.request(True, 0, schema, 1, 2, 3, 4, 5) + assert type(res.exception()) == ValueError + assert cluster._endpoint.request.call_count == 0 + cluster._endpoint.request.reset_mock() + + def test_reply_general(cluster): cluster.reply(False, 0, []) assert cluster._endpoint.reply.call_count == 1 diff --git a/zigpy/types/basic.py b/zigpy/types/basic.py index 187e2cdf8..adbc016a9 100644 --- a/zigpy/types/basic.py +++ b/zigpy/types/basic.py @@ -279,3 +279,17 @@ def serialize(self): raise ValueError("String is too long") return super().serialize() return LimitedCharString + + +def Optional(optional_item_type): + class Optional(optional_item_type): + optional = True + + @classmethod + def deserialize(cls, data): + try: + return super().deserialize(data) + except ValueError: + return None, b'' + + return Optional diff --git a/zigpy/zcl/__init__.py b/zigpy/zcl/__init__.py index cbae597e2..b63b93cf3 100644 --- a/zigpy/zcl/__init__.py +++ b/zigpy/zcl/__init__.py @@ -100,7 +100,8 @@ def deserialize(self, tsn, frame_type, is_reply, command_id, data): @util.retryable_request def request(self, general, command_id, schema, *args, manufacturer=None, expect_reply=True): - if len(schema) != len(args): + optional = len([s for s in schema if hasattr(s, 'optional') and s.optional]) + if len(schema) < len(args) or len(args) < len(schema) - optional: self.error("Schema and args lengths do not match in request") error = asyncio.Future() error.set_exception(ValueError("Wrong number of parameters for request, expected %d argument(s)" % len(schema))) diff --git a/zigpy/zcl/clusters/general.py b/zigpy/zcl/clusters/general.py index 53b64c6b2..aa68a04e2 100644 --- a/zigpy/zcl/clusters/general.py +++ b/zigpy/zcl/clusters/general.py @@ -219,7 +219,8 @@ class Scenes(Cluster): 0x0002: ('remove_response', (t.uint8_t, t.uint16_t, t.uint8_t), True), 0x0003: ('remove_all_response', (t.uint8_t, t.uint16_t), True), 0x0004: ('store_response', (t.uint8_t, t.uint16_t, t.uint8_t), True), - 0x0006: ('get_scene_membership_response', (t.uint8_t, t.uint8_t, t.uint16_t, t.LVList(t.uint8_t)), True), + 0x0006: ('get_scene_membership_response', (t.uint8_t, t.uint8_t, t.uint16_t, + t.Optional(t.LVList(t.uint8_t))), True), 0x0040: ('enhanced_add_response', (), True), 0x0041: ('enhanced_view_response', (), True), 0x0042: ('copy_response', (), True), @@ -311,7 +312,9 @@ class Alarms(Cluster): } client_commands = { 0x0000: ('alarm', (t.uint8_t, t.uint16_t), False), - 0x0001: ('get_alarm_response', (t.uint8_t, t.uint8_t, t.uint16_t, t.uint32_t), True), + 0x0001: ('get_alarm_response', (t.uint8_t, t.Optional(t.uint8_t), + t.Optional(t.uint16_t,), + t.Optional(t.uint32_t)), True), 0x0002: ('get_event_log', (), False), } @@ -405,8 +408,15 @@ class NeighborInfo(t.Struct): ] client_commands = { - 0x0000: ('dev_config_response', (t.uint8_t, t.int16s, t.uint16_t, t.uint16_t, t.uint8_t, t.uint16_t), True), - 0x0001: ('location_data_response', (t.uint8_t, t.uint8_t, t.int16s, t.int16s, t.int16s, t.uint16_t, t.uint8_t, t.uint8_t, t.uint16_t), True), + 0x0000: ('dev_config_response', (foundation.Status, + t.Optional(t.int16s), t.Optional(t.uint16_t), + t.Optional(t.uint16_t), t.Optional(t.uint8_t), + t.Optional(t.uint16_t)), True), + 0x0001: ('location_data_response', (foundation.Status, + t.Optional(t.uint8_t), t.Optional(t.int16s), + t.Optional(t.int16s), t.Optional(t.int16s), + t.Optional(t.uint16_t), t.Optional(t.uint8_t), + t.Optional(t.uint8_t), t.Optional(t.uint16_t)), True), 0x0002: ('location_data_notification', (), False), 0x0003: ('compact_location_data_notification', (), False), 0x0004: ('rssi_ping', (t.uint8_t, ), False), # data8 @@ -666,18 +676,23 @@ class Ota(Cluster): 0x000a: ('image_stamp', t.uint32_t), } server_commands = { - 0x0001: ('query_next_image', (t.uint8_t, t.uint16_t, t.uint16_t, t.uint32_t, t.uint16_t), False), - 0x0003: ('image_block', (t.uint8_t, t.uint16_t, t.uint16_t, t.uint32_t, t.uint32_t, t.uint8_t, t.EUI64, t.uint16_t), False), - 0x0004: ('image_page', (t.uint8_t, t.uint16_t, t.uint16_t, t.uint32_t, t.uint32_t, t.uint8_t, t.uint16_t, t.uint16_t, t.EUI64), False), + 0x0001: ('query_next_image', (t.uint8_t, t.uint16_t, t.uint16_t, t.uint32_t, t.Optional(t.uint16_t)), False), + 0x0003: ('image_block', (t.uint8_t, t.uint16_t, t.uint16_t, t.uint32_t, t.uint32_t, t.uint8_t, + t.Optional(t.EUI64), t.Optional(t.uint16_t)), False), + 0x0004: ('image_page', (t.uint8_t, t.uint16_t, t.uint16_t, t.uint32_t, t.uint32_t, t.uint8_t, t.uint16_t, + t.uint16_t, t.Optional(t.EUI64)), False), 0x0006: ('upgrade_end', (foundation.Status, t.uint16_t, t.uint16_t, t.uint32_t), False), 0x0008: ('query_specific_file', (t.EUI64, t.uint16_t, t.uint16_t, t.uint32_t, t.uint16_t), False), } client_commands = { - 0x0000: ('image_notify', (t.uint8_t, t.uint8_t, t.uint16_t, t.uint16_t, t.uint32_t), False), - 0x0002: ('query_next_image_response', (foundation.Status, t.uint16_t, t.uint16_t, t.uint32_t, t.uint32_t), True), + 0x0000: ('image_notify', (t.uint8_t, t.uint8_t, t.Optional(t.uint16_t), t.Optional(t.uint16_t), + t.Optional(t.uint32_t)), False), + 0x0002: ('query_next_image_response', (foundation.Status, t.Optional(t.uint16_t), t.Optional(t.uint16_t), + t.Optional(t.uint32_t), t.Optional(t.uint32_t)), True), 0x0005: ('image_block_response', (foundation.Status, t.uint16_t, t.uint16_t, t.uint32_t, t.uint32_t, t.LVBytes), True), 0x0007: ('upgrade_end_response', (t.uint16_t, t.uint16_t, t.uint32_t, t.uint32_t, t.uint32_t), True), - 0x0009: ('query_specific_file_response', (foundation.Status, t.uint16_t, t.uint16_t, t.uint32_t, t.uint32_t), True), + 0x0009: ('query_specific_file_response', (foundation.Status, t.Optional(t.uint16_t), t.Optional(t.uint16_t), + t.Optional(t.uint32_t), t.Optional(t.uint32_t)), True), } @@ -738,7 +753,7 @@ class PowerProfile(t.Struct): 0x0008: ('energy_phases_schedule_state_notification', (t.uint8_t, t.uint8_t), False), 0x0009: ('power_profile_schedule_constraints_notification', (t.uint8_t, t.uint16_t, t.uint16_t), False), 0x000a: ('power_profile_schedule_constraints_response', (t.uint8_t, t.uint16_t, t.uint16_t), True), - 0x000b: ('get_power_profile_price_extended', (t.bitmap8, t.uint8_t, t.uint16_t), False), + 0x000b: ('get_power_profile_price_extended', (t.bitmap8, t.uint8_t, t.Optional(t.uint16_t)), False), } diff --git a/zigpy/zcl/clusters/lightlink.py b/zigpy/zcl/clusters/lightlink.py index 9b822eeb4..cac36f2c2 100644 --- a/zigpy/zcl/clusters/lightlink.py +++ b/zigpy/zcl/clusters/lightlink.py @@ -54,8 +54,10 @@ class LightLink(Cluster): 0x0042: ('get_endpoint_list', (t.uint8_t, ), False), } client_commands = { - # TODO: 'scan_rsp` may have dynamic argument count response - # 0x0001: ('scan_rsp', (t.uint32_t, t.uint8_t, t.bitmap8, t.bitmap8, t.bitmap16, t.uint32_t, t.EUI64, t.uint8_t, t.uint8_t, t.uint16_t, t.uint16_t, t.uint8_t, t.uint8_t, t.uint8_t, t.uint8_t, t.uint16_t, t.uint16_t, t.uint8_t, t.uint8_t ), True), + 0x0001: ('scan_rsp', (t.uint32_t, t.uint8_t, t.bitmap8, t.bitmap8, t.bitmap16, t.uint32_t, t.EUI64, t.uint8_t, + t.uint8_t, t.uint16_t, t.uint16_t, t.uint8_t, t.uint8_t, t.Optional(t.uint8_t), + t.Optional(t.uint16_t), t.Optional(t.uint16_t), t.Optional(t.uint8_t), + t.Optional(t.uint8_t)), True), 0x0003: ('device_information_rsp', (t.uint32_t, t.uint8_t, t.uint8_t, t.LVList(DeviceInfoRecord), ), True), 0x0011: ('network_start_rsp', (t.uint32_t, foundation.Status, t.EUI64, t.uint8_t, t.uint8_t, t.uint16_t, ), True), 0x0013: ('network_join_router_rsp', (t.uint32_t, foundation.Status, ), True), diff --git a/zigpy/zdo/types.py b/zigpy/zdo/types.py index 11c1448df..c70adc28f 100644 --- a/zigpy/zdo/types.py +++ b/zigpy/zdo/types.py @@ -391,15 +391,22 @@ class ZDOCmd(_CommandID, enum.Enum): # Responses # Device and Service Discovery Server Responses - ZDOCmd.NWK_addr_rsp: (STATUS, IEEE, NWK, ('NumAssocDev', t.uint8_t), ('StartIndex', t.uint8_t), ('NWKAddressAssocDevList', t.List(t.uint16_t))), - ZDOCmd.IEEE_addr_rsp: (STATUS, IEEE, NWK, ('NumAssocDev', t.uint8_t), ('StartIndex', t.uint8_t), ('NWKAddrAssocDevList', t.List(t.uint16_t))), - ZDOCmd.Node_Desc_rsp: (STATUS, NWKI, ('NodeDescriptor', NodeDescriptor)), - ZDOCmd.Power_Desc_rsp: (STATUS, NWKI, ('PowerDescriptor', PowerDescriptor)), - ZDOCmd.Simple_Desc_rsp: (STATUS, NWKI, ('SimpleDescriptor', SizePrefixedSimpleDescriptor)), + ZDOCmd.NWK_addr_rsp: (STATUS, IEEE, NWK, + ('NumAssocDev', t.Optional(t.uint8_t)), + ('StartIndex', t.Optional(t.uint8_t)), + ('NWKAddressAssocDevList', t.Optional(t.List(t.NWK)))), + ZDOCmd.IEEE_addr_rsp: (STATUS, IEEE, NWK, + ('NumAssocDev', t.Optional(t.uint8_t)), + ('StartIndex', t.Optional(t.uint8_t)), + ('NWKAddrAssocDevList', t.Optional(t.List(t.NWK)))), + ZDOCmd.Node_Desc_rsp: (STATUS, NWKI, ('NodeDescriptor', t.Optional(NodeDescriptor))), + ZDOCmd.Power_Desc_rsp: (STATUS, NWKI, ('PowerDescriptor', t.Optional(PowerDescriptor))), + ZDOCmd.Simple_Desc_rsp: (STATUS, NWKI, ('SimpleDescriptor', t.Optional(SizePrefixedSimpleDescriptor))), ZDOCmd.Active_EP_rsp: (STATUS, NWKI, ('ActiveEPList', t.LVList(t.uint8_t))), ZDOCmd.Match_Desc_rsp: (STATUS, NWKI, ('MatchList', t.LVList(t.uint8_t))), - # ZDO.Complex_Desc_rsp: (STATUS, NWKI, ('Length', t.uint8_t), ('ComplexDescriptor', ComplexDescriptor)), - ZDOCmd.User_Desc_rsp: (STATUS, NWKI, ('Length', t.uint8_t), ('UserDescriptor', t.fixed_list(16, t.uint8_t))), + # ZDO.Complex_Desc_rsp: (STATUS, NWKI, ('Length', t.uint8_t), ('ComplexDescriptor', t.Optional(ComplexDescriptor))), + ZDOCmd.User_Desc_rsp: (STATUS, NWKI, ('Length', t.uint8_t), + ('UserDescriptor', t.Optional(t.fixed_list(16, t.uint8_t)))), ZDOCmd.Discovery_Cache_rsp: (STATUS,), ZDOCmd.User_Desc_conf: (STATUS, NWKI), ZDOCmd.System_Server_Discovery_rsp: (STATUS, ('ServerMask', t.uint16_t)), @@ -410,7 +417,9 @@ class ZDOCmd(_CommandID, enum.Enum): ZDOCmd.Simple_Desc_store_rsp: (STATUS,), ZDOCmd.Remove_node_cache_rsp: (STATUS,), ZDOCmd.Find_node_cache_rsp: (('CacheNWKAddr', t.EUI64), NWK, IEEE), - ZDOCmd.Extended_Simple_Desc_rsp: (STATUS, NWK, ('Endpoint', t.uint8_t), ('AppInputClusterCount', t.uint8_t), ('AppOutputClusterCount', t.uint8_t), ('StartIndex', t.uint8_t), ('AppClusterList', t.List(t.uint16_t))), + ZDOCmd.Extended_Simple_Desc_rsp: (STATUS, NWK, ('Endpoint', t.uint8_t), ('AppInputClusterCount', t.uint8_t), + ('AppOutputClusterCount', t.uint8_t), ('StartIndex', t.uint8_t), + ('AppClusterList', t.Optional(t.List(t.uint16_t)))), ZDOCmd.Extended_Active_EP_rsp: (STATUS, NWKI, ('ActiveEPCount', t.uint8_t), ('StartIndex', t.uint8_t), ('ActiveEPList', t.List(t.uint8_t))), # Bind Management Server Services Responses ZDOCmd.End_Device_Bind_rsp: (STATUS,), From 045e302c2e50d76c76d1cf30d280110b1bb99210 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 23 May 2019 11:47:52 -0400 Subject: [PATCH 06/86] version bump to 0.4.1 --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 6bfa3c455..b3966b80f 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 4 -PATCH_VERSION = '0' +PATCH_VERSION = '1' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) From 40649470d265cb0149c014a01c3fc2aa9235ae21 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 29 May 2019 22:04:52 -0400 Subject: [PATCH 07/86] version 0.4.2 --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index a0d7bb042..eec44005b 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 5 -PATCH_VERSION = '0.dev0' +MINOR_VERSION = 4 +PATCH_VERSION = '2' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) From 274e783b46b21f4b42c01fcedb41382e062c66da Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 11 Jun 2019 12:59:21 -0400 Subject: [PATCH 08/86] bump version to 0.5.0 --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index a0d7bb042..fafbe7d19 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 5 -PATCH_VERSION = '0.dev0' +PATCH_VERSION = '0' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) From 7124ad3be2f600e96fd20f1742e5e163446f6be7 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 22 Jun 2019 20:32:54 -0400 Subject: [PATCH 09/86] Bump version to 0.6.0 --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index dfda2c080..3d0c87487 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 6 -PATCH_VERSION = '0.dev0' +PATCH_VERSION = '0' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) From df24df1e930b172952e2844122ed8a40c52f69c5 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 22 Jun 2019 22:34:56 -0400 Subject: [PATCH 10/86] 0.6.1 Release. (#189) * 0.6.1 version bump * Don't override endpoint's manufacturer/model from quirks. (#187) --- zigpy/__init__.py | 2 +- zigpy/quirks/__init__.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 3d0c87487..689c0cdb6 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 6 -PATCH_VERSION = '0' +PATCH_VERSION = '1' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) diff --git a/zigpy/quirks/__init__.py b/zigpy/quirks/__init__.py index dee0659bf..f9559b2fa 100644 --- a/zigpy/quirks/__init__.py +++ b/zigpy/quirks/__init__.py @@ -76,8 +76,6 @@ def set_device_attr(attr): set_device_attr('profile_id') set_device_attr('device_type') - set_device_attr('manufacturer') - set_device_attr('model') self.status = zigpy.endpoint.Status.ZDO_INIT for c in replacement_data.get('input_clusters', []): From 1f816a39a99249cf132f32dca7793820494641c5 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 9 Jul 2019 21:57:12 -0400 Subject: [PATCH 11/86] 0.7.0 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index d8e5538bf..dc05b9931 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 7 -PATCH_VERSION = '0.dev0' +PATCH_VERSION = '0' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) From de054e6cb10fed752af0f1cd916bcacc71f6685b Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Mon, 12 Aug 2019 11:39:34 -0500 Subject: [PATCH 12/86] Don't quirk quirked devices (#199) * don't requirk a quirked device * move import --- zigpy/quirks/registry.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zigpy/quirks/registry.py b/zigpy/quirks/registry.py index f3f2e2c30..5f3d37e93 100644 --- a/zigpy/quirks/registry.py +++ b/zigpy/quirks/registry.py @@ -1,6 +1,7 @@ import collections import itertools import logging +import zigpy.quirks _LOGGER = logging.getLogger(__name__) @@ -35,6 +36,8 @@ def remove(self, custom_device): def get_device(self, device): """Get a CustomDevice object, if one is available""" + if isinstance(device, zigpy.quirks.CustomDevice): + return device dev_ep = set(device.endpoints) - set([0]) _LOGGER.debug("Checking quirks for %s %s (%s)", device.manufacturer, device.model, device.ieee) From cb6b06d897f0a9b8e6e396a3135b26d4be9f1dbd Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Mon, 12 Aug 2019 12:48:18 -0400 Subject: [PATCH 13/86] 0.7.1 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index dc05b9931..c50ac0bb4 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 7 -PATCH_VERSION = '0' +PATCH_VERSION = '1' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) From 51ba2bc8821adad21c470ff39b2a70a93222f30b Mon Sep 17 00:00:00 2001 From: Hedda Date: Tue, 20 Aug 2019 16:42:07 +0200 Subject: [PATCH 14/86] Update README.md to mention experimental ZiGate support (#204) Update README.md to mention experimental ZiGate support plus links to code/library and hardware. This replaces #115 @doudz has now publish zigpy-zigate v0.1.0 which has experimental support for ZiGate to Zigpy https://github.com/doudz/zigpy-zigate zigpy-zigate 0.1.0 release on PyPI https://pypi.org/project/zigpy-zigate/#history Requires ZiGate firmware 3.1a or later firmware version which has added a raw mode https://zigate.fr/tag/firmware/ --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0cdc6df9c..b4489fcb1 100644 --- a/README.md +++ b/README.md @@ -23,5 +23,9 @@ zigpy works with separate radio libraries which can each interface with multiple - [ConBee](https://www.dresden-elektronik.de/conbee/) USB adio adapter from [Dresden-Elektronik](https://www.dresden-elektronik.de) - [RaspBee](https://www.dresden-elektronik.de/raspbee/) GPIO radio adapter from [Dresden-Elektronik](https://www.dresden-elektronik.de) - **Related projects:** - ZHA deviation handling in Home Assistant relies on on the third-party [ZHA Device Handlers](https://github.com/dmulcahey/zha-device-handlers) project. Zigbee devices that deviate from or do not fully conform to the standard specifications set by the [Zigbee Alliance](https://www.zigbee.org) may require the development of custom [ZHA Device Handlers](https://github.com/dmulcahey/zha-device-handlers) (ZHA custom quirks handler implementation) to for all their functions to work properly with the ZHA component in Home Assistant. These ZHA Device Handlers for Home Assistant can thus be used to parse custom messages to and from non-compliant Zigbee devices. The custom quirks implementations for zigpy implemented as ZHA Device Handlers for Home Assistant are a similar concept to that of [Hub-connected Device Handlers for the SmartThings Classics platform](https://docs.smartthings.com/en/latest/device-type-developers-guide/) as well as that of [Zigbee-Shepherd Converters as used by Zigbee2mqtt](https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html), meaning they are each virtual representations of a physical device that expose additional functionality that is not provided out-of-the-box by the existing integration between these platforms. +**Experimental Zigbee radio modules:** +- ZiGate based radios (via the [zigpy-zigate](https://github.com/doudz/zigpy-zigate) library for zigpy) + - [ZiGate open source ZigBee adapter hardware](https://zigate.fr/) + +**Related projects:** +ZHA deviation handling in Home Assistant relies on on the third-party [ZHA Device Handlers](https://github.com/dmulcahey/zha-device-handlers) project. Zigbee devices that deviate from or do not fully conform to the standard specifications set by the [Zigbee Alliance](https://www.zigbee.org) may require the development of custom [ZHA Device Handlers](https://github.com/dmulcahey/zha-device-handlers) (ZHA custom quirks handler implementation) to for all their functions to work properly with the ZHA component in Home Assistant. These ZHA Device Handlers for Home Assistant can thus be used to parse custom messages to and from non-compliant Zigbee devices. The custom quirks implementations for zigpy implemented as ZHA Device Handlers for Home Assistant are a similar concept to that of [Hub-connected Device Handlers for the SmartThings Classics platform](https://docs.smartthings.com/en/latest/device-type-developers-guide/) as well as that of [Zigbee-Shepherd Converters as used by Zigbee2mqtt](https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html), meaning they are each virtual representations of a physical device that expose additional functionality that is not provided out-of-the-box by the existing integration between these platforms. From b82dab7d126ad2ac1119fddb8926d8892b7dfbaf Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 7 Sep 2019 19:01:18 -0400 Subject: [PATCH 15/86] Differentiate input/output cluster instances. (#216) --- tests/test_endpoint.py | 4 ++++ zigpy/endpoint.py | 6 ++++-- zigpy/quirks/__init__.py | 4 ++-- zigpy/zcl/__init__.py | 30 +++++++++++++++++++++++++----- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/tests/test_endpoint.py b/tests/test_endpoint.py index 512511d6f..3ba2546ab 100644 --- a/tests/test_endpoint.py +++ b/tests/test_endpoint.py @@ -69,6 +69,8 @@ async def test_reinitialize(ep): def test_add_input_cluster(ep): ep.add_input_cluster(0) assert 0 in ep.in_clusters + assert ep.in_clusters[0].is_server is True + assert ep.in_clusters[0].is_client is False def test_add_custom_input_cluster(ep): @@ -81,6 +83,8 @@ def test_add_custom_input_cluster(ep): def test_add_output_cluster(ep): ep.add_output_cluster(0) assert 0 in ep.out_clusters + assert ep.out_clusters[0].is_server is False + assert ep.out_clusters[0].is_client is True def test_add_custom_output_cluster(ep): diff --git a/zigpy/endpoint.py b/zigpy/endpoint.py index 2ac94e3f9..425f1196e 100644 --- a/zigpy/endpoint.py +++ b/zigpy/endpoint.py @@ -82,7 +82,8 @@ def add_input_cluster(self, cluster_id, cluster=None): return self.in_clusters[cluster_id] if cluster is None: - cluster = zigpy.zcl.Cluster.from_id(self, cluster_id) + cluster = zigpy.zcl.Cluster.from_id(self, cluster_id, + is_server=True) self.in_clusters[cluster_id] = cluster if hasattr(cluster, 'ep_attribute'): self._cluster_attr[cluster.ep_attribute] = cluster @@ -105,7 +106,8 @@ def add_output_cluster(self, cluster_id, cluster=None): return self.out_clusters[cluster_id] if cluster is None: - cluster = zigpy.zcl.Cluster.from_id(self, cluster_id) + cluster = zigpy.zcl.Cluster.from_id(self, cluster_id, + is_server=False) self.out_clusters[cluster_id] = cluster return cluster diff --git a/zigpy/quirks/__init__.py b/zigpy/quirks/__init__.py index f9559b2fa..33a417e18 100644 --- a/zigpy/quirks/__init__.py +++ b/zigpy/quirks/__init__.py @@ -83,7 +83,7 @@ def set_device_attr(attr): cluster = None cluster_id = c else: - cluster = c(self) + cluster = c(self, is_server=True) cluster_id = cluster.cluster_id self.add_input_cluster(cluster_id, cluster) @@ -92,7 +92,7 @@ def set_device_attr(attr): cluster = None cluster_id = c else: - cluster = c(self) + cluster = c(self, is_server=False) cluster_id = cluster.cluster_id self.add_output_cluster(cluster_id, cluster) diff --git a/zigpy/zcl/__init__.py b/zigpy/zcl/__init__.py index b63b93cf3..5727fe61a 100644 --- a/zigpy/zcl/__init__.py +++ b/zigpy/zcl/__init__.py @@ -1,5 +1,6 @@ import asyncio import functools +import enum import logging import zigpy.types as t @@ -38,6 +39,11 @@ def __init__(cls, name, bases, nmspc): # noqa: N805 cls._registry_range[cls.cluster_id_range] = cls +class ClusterType(enum.IntEnum): + Server = 0 + Client = 1 + + class Cluster(util.ListenableMixin, util.LocalLogMixin, metaclass=Registry): """A cluster on an endpoint""" _registry = {} @@ -45,24 +51,28 @@ class Cluster(util.ListenableMixin, util.LocalLogMixin, metaclass=Registry): _server_command_idx = {} _client_command_idx = {} - def __init__(self, endpoint): + def __init__(self, endpoint, is_server=True): self._endpoint = endpoint self._attr_cache = {} self._listeners = {} + if is_server: + self._type = ClusterType.Server + else: + self._type = ClusterType.Client @classmethod - def from_id(cls, endpoint, cluster_id): + def from_id(cls, endpoint, cluster_id, is_server=True): if cluster_id in cls._registry: - return cls._registry[cluster_id](endpoint) + return cls._registry[cluster_id](endpoint, is_server) else: for cluster_id_range, cluster in cls._registry_range.items(): if cluster_id_range[0] <= cluster_id <= cluster_id_range[1]: - c = cluster(endpoint) + c = cluster(endpoint, is_server) c.cluster_id = cluster_id return c LOGGER.warning("Unknown cluster %s", cluster_id) - c = cls(endpoint) + c = cls(endpoint, is_server) c.cluster_id = cluster_id return c @@ -305,6 +315,16 @@ def client_command(self, command, *args): schema = self.client_commands[command][1] return self.reply(False, command, schema, *args) + @property + def is_client(self) -> bool: + """Return True if this is a client cluster.""" + return self._type == ClusterType.Client + + @property + def is_server(self) -> bool: + """Return True if this is a server cluster.""" + return self._type == ClusterType.Server + @property def name(self): return self.__class__.__name__ From 067b85d9688951d3e6b74a034b3f36d08025d99c Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 7 Sep 2019 19:10:17 -0400 Subject: [PATCH 16/86] 0.7.2 Version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index c50ac0bb4..31ee79fac 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 7 -PATCH_VERSION = '1' +PATCH_VERSION = '2' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) From 7c2293d180e7860f57d91029d74d2a8232534b2f Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 10 Sep 2019 10:13:53 -0400 Subject: [PATCH 17/86] 0.8.0 Version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 61032e0ed..a3ff749b2 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 8 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From ae630157d3efe7952d8d0177e7cca558b439c5e3 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 19 Sep 2019 10:58:08 -0400 Subject: [PATCH 18/86] 0.9.0 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 9e700284e..402f1790a 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 9 -PATCH_VERSION = "0a3" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 988e29d3c5c91a705debb52be13428434bce0881 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 15 Oct 2019 17:42:49 -0400 Subject: [PATCH 19/86] 0.10.0 Release. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 66dfb1c26..edf073c77 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 10 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 55279566c221c8f8ce9b9aa90be4af2fb90673aa Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 10 Nov 2019 09:57:16 -0500 Subject: [PATCH 20/86] 0.11.0 version bump. --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index eb28e3c82..1f1b828a5 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 10 -PATCH_VERSION = "1.dev0" +MINOR_VERSION = 11 +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 9f76d81f8331dc1cab8a8f48a92b97960fae87f2 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 26 Dec 2019 13:08:31 -0500 Subject: [PATCH 21/86] Version bump 0.12.0 --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 1712306f4..025a43df9 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 12 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 8df6241d16499f5ca39ac3c3c37773bd52174252 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 28 Jan 2020 21:57:39 -0500 Subject: [PATCH 22/86] 0.13.0 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 01aac61c3..a06900461 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 13 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From f8dddd1ba71b5bea1a046ff24088ba2cbe320ce3 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 6 Feb 2020 15:26:26 -0500 Subject: [PATCH 23/86] 0.13.1 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 01aac61c3..ed5782fd1 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 13 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "1" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 166aaacbdcbeba1079109173a056c2cc651dd1a7 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 7 Feb 2020 23:51:34 -0500 Subject: [PATCH 24/86] Deffer attributes updates for uninitialized devices. (#290) * Test node_descriptor for uninitialized device. Don't save node descriptor if device wasn't fully initialized. * Attribute_update tests. Don't update attributes in persistent storage if device is not fully initialized. * fixup-test * Deffered node_descriptor and attribute updates. Don't update node_descriptor and attributes in the persistent storage, unless device was fully initialized. * Don't save uninitialized device. * Relax attribute DB schema. Don't enforce cluster_id as a foreign key for attributes. * Fix test coverage. --- tests/test_appdb.py | 102 ++++++++++++++++++++++++++++++++---------- zigpy/appdb.py | 30 ++++++++++--- zigpy/zcl/__init__.py | 3 ++ 3 files changed, 105 insertions(+), 30 deletions(-) diff --git a/tests/test_appdb.py b/tests/test_appdb.py index 887b6ec9d..3e83f6c7e 100644 --- a/tests/test_appdb.py +++ b/tests/test_appdb.py @@ -25,33 +25,34 @@ def make_ieee(init=0): class FakeCustomDevice(CustomDevice): - def __init__(self, application, ieee, nwk, replaces): - super().__init__(application, ieee, nwk, replaces) + pass -async def _initialize(self): - self.status = Status.ENDPOINTS_INIT - self.initializing = False - self._application.device_initialized(self) +def mock_dev_init(status: Status): + """Device schedule_initialize mock factory.""" + + def _initialize(self): + self.status = status + self.initializing = False + self._application.device_initialized(self) + self.node_desc = zdo_t.NodeDescriptor(0, 1, 2, 3, 4, 5, 6, 7, 8) + + return _initialize def fake_get_device(device): if device.endpoints.get(1) is not None and device[1].profile_id == 65535: - return FakeCustomDevice( - device.application, - make_ieee(1), - 199, - Device(device.application, make_ieee(1), 199), - ) + return FakeCustomDevice(device.application, make_ieee(1), 199, device) return device @pytest.mark.asyncio async def test_database(tmpdir, monkeypatch): - monkeypatch.setattr(Device, "_initialize", _initialize) + monkeypatch.setattr( + Device, "schedule_initialize", mock_dev_init(Status.ENDPOINTS_INIT) + ) db = os.path.join(str(tmpdir), "test.db") app = make_app(db) - # TODO: Leaks a task on dev.initialize, I think? ieee = make_ieee() relays_1 = [t.NWK(0x1234), t.NWK(0x2345)] relays_2 = [t.NWK(0x3456), t.NWK(0x4567)] @@ -59,7 +60,6 @@ async def test_database(tmpdir, monkeypatch): app.handle_join(99, ieee, 0) dev = app.get_device(ieee) - dev.node_desc, _ = zdo_t.NodeDescriptor.deserialize(b"1234567890123") ep = dev.add_endpoint(1) ep.profile_id = 260 ep.device_type = profiles.zha.DeviceType.PUMP @@ -136,9 +136,11 @@ async def mockleave(*args, **kwargs): def _test_null_padded(tmpdir, test_manufacturer=None, test_model=None): db = os.path.join(str(tmpdir), "test.db") app = make_app(db) - # TODO: Leaks a task on dev.initialize, I think? ieee = make_ieee() - with mock.patch("zigpy.device.Device.schedule_initialize"): + with mock.patch( + "zigpy.device.Device.schedule_initialize", + new=mock_dev_init(Status.ENDPOINTS_INIT), + ): app.handle_join(99, ieee, 0) app.handle_join(99, ieee, 0) @@ -210,13 +212,17 @@ def test_appdb_str_model(tmpdir): assert dev.endpoints[3].model == "Mock Model" +@pytest.mark.parametrize( + "status, success", + ((Status.ENDPOINTS_INIT, True), (Status.ZDO_INIT, False), (Status.NEW, False)), +) @pytest.mark.asyncio -async def test_node_descriptor_updated(tmpdir, monkeypatch): - monkeypatch.setattr(Device, "_initialize", _initialize) +async def test_node_descriptor_updated(tmpdir, status, success): db = os.path.join(str(tmpdir), "test_nd.db") app = make_app(db) nd_ieee = make_ieee(2) - app.handle_join(299, nd_ieee, 0) + with mock.patch.object(Device, "schedule_initialize", new=mock_dev_init(status)): + app.handle_join(299, nd_ieee, 0) dev = app.get_device(nd_ieee) ep = dev.add_endpoint(1) @@ -239,16 +245,22 @@ async def mock_get_node_descriptor(): assert dev.get_node_descriptor.call_count == 1 app2 = make_app(db) - dev = app2.get_device(nd_ieee) - assert dev.node_desc.is_valid - assert dev.node_desc.serialize() == b"abcdefghijklm" + if success: + dev = app2.get_device(nd_ieee) + assert dev.status == status + assert dev.node_desc.is_valid + assert dev.node_desc.serialize() == b"abcdefghijklm" + else: + assert nd_ieee not in app2.devices os.unlink(db) @pytest.mark.asyncio async def test_groups(tmpdir, monkeypatch): - monkeypatch.setattr(Device, "_initialize", _initialize) + monkeypatch.setattr( + Device, "schedule_initialize", mock_dev_init(Status.ENDPOINTS_INIT) + ) group_id, group_name = 0x1221, "app db Test Group 0x1221" @@ -324,3 +336,45 @@ async def mock_request(*args, **kwargs): app5 = make_app(db) assert not app5.groups + + +@pytest.mark.parametrize( + "status, success", + ((Status.ENDPOINTS_INIT, True), (Status.ZDO_INIT, False), (Status.NEW, False)), +) +def test_attribute_update(tmpdir, status, success): + """Test attribute update for initialized and uninitialized devices.""" + + db = os.path.join(str(tmpdir), "test.db") + app = make_app(db) + ieee = make_ieee() + with mock.patch( + "zigpy.device.Device.schedule_initialize", new=mock_dev_init(status) + ): + app.handle_join(99, ieee, 0) + + test_manufacturer = "Test Manufacturer" + test_model = "Test Model" + + dev = app.get_device(ieee) + ep = dev.add_endpoint(3) + ep.profile_id = 260 + ep.device_type = profiles.zha.DeviceType.PUMP + clus = ep.add_input_cluster(0) + ep.add_output_cluster(1) + clus._update_attribute(4, test_manufacturer) + clus._update_attribute(5, test_model) + app.device_initialized(dev) + + # Everything should've been saved - check that it re-loads + app2 = make_app(db) + if success: + dev = app2.get_device(ieee) + assert dev.status == status + assert dev.endpoints[3].device_type == profiles.zha.DeviceType.PUMP + assert dev.endpoints[3].in_clusters[0]._attr_cache[4] == test_manufacturer + assert dev.endpoints[3].in_clusters[0]._attr_cache[5] == test_model + else: + assert ieee not in app2.devices + + os.unlink(db) diff --git a/zigpy/appdb.py b/zigpy/appdb.py index d05555815..5f8f2bd68 100644 --- a/zigpy/appdb.py +++ b/zigpy/appdb.py @@ -171,8 +171,8 @@ def _create_table_attributes(self): "attributes", ( "(ieee ieee, endpoint_id, cluster, attrid, value, " - "FOREIGN KEY(ieee, endpoint_id, cluster) " - "REFERENCES clusters(ieee, endpoint_Id, cluster) " + "FOREIGN KEY(ieee, endpoint_id) " + "REFERENCES endpoints(ieee, endpoint_id) " "ON DELETE CASCADE)" ), ) @@ -218,6 +218,14 @@ def _remove_device(self, device): self._db.commit() def _save_device(self, device): + if device.status != zigpy.device.Status.ENDPOINTS_INIT: + LOGGER.warning( + "Not saving uninitialized %s/%s device: %s", + device.ieee, + device.nwk, + device.status, + ) + return q = "INSERT OR REPLACE INTO devices (ieee, nwk, status) VALUES (?, ?, ?)" self.execute(q, (device.ieee, device.nwk, device.status)) self._save_node_descriptor(device) @@ -230,6 +238,7 @@ def _save_device(self, device): # ZDO continue self._save_input_clusters(ep) + self._save_attribute_cache(ep) self._save_output_clusters(ep) self._db.commit() @@ -249,10 +258,12 @@ def _save_endpoints(self, device): ) endpoints.append(eprow) self._cursor.executemany(q, endpoints) - self._db.commit() def _save_node_descriptor(self, device): - if not device.node_desc.is_valid: + if ( + device.status != zigpy.device.Status.ENDPOINTS_INIT + or not device.node_desc.is_valid + ): return q = "INSERT OR REPLACE INTO node_descriptors VALUES (?, ?)" self.execute(q, (device.ieee, device.node_desc.serialize())) @@ -264,7 +275,15 @@ def _save_input_clusters(self, endpoint): for cluster in endpoint.in_clusters.values() ] self._cursor.executemany(q, clusters) - self._db.commit() + + def _save_attribute_cache(self, ep): + q = "INSERT OR REPLACE INTO attributes VALUES (?, ?, ?, ?, ?)" + clusters = [ + (ep.device.ieee, ep.endpoint_id, cluster.cluster_id, attrid, value) + for cluster in ep.in_clusters.values() + for attrid, value in cluster._attr_cache.items() + ] + self._cursor.executemany(q, clusters) def _save_output_clusters(self, endpoint): q = "INSERT OR REPLACE INTO output_clusters VALUES (?, ?, ?)" @@ -273,7 +292,6 @@ def _save_output_clusters(self, endpoint): for cluster in endpoint.out_clusters.values() ] self._cursor.executemany(q, clusters) - self._db.commit() def _save_attribute(self, ieee, endpoint_id, cluster_id, attrid, value): q = "INSERT OR REPLACE INTO attributes VALUES (?, ?, ?, ?, ?)" diff --git a/zigpy/zcl/__init__.py b/zigpy/zcl/__init__.py index cc0201e86..16ab4259d 100644 --- a/zigpy/zcl/__init__.py +++ b/zigpy/zcl/__init__.py @@ -6,6 +6,7 @@ import zigpy.types as t from zigpy import util from zigpy.zcl import foundation +import zigpy.device LOGGER = logging.getLogger(__name__) @@ -439,6 +440,8 @@ def __init__(self, applistener, cluster): self._cluster = cluster def attribute_updated(self, attrid, value): + if self._cluster.endpoint.device.status != zigpy.device.Status.ENDPOINTS_INIT: + return self._applistener.attribute_updated(self._cluster, attrid, value) def cluster_command(self, *args, **kwargs): From 4ac2e6d0ad90df2f439c781c2ba33a28cd2e3391 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 7 Feb 2020 23:54:58 -0500 Subject: [PATCH 25/86] 0.13.2 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index ed5782fd1..24a995926 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 13 -PATCH_VERSION = "1" +PATCH_VERSION = "2" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From ca3cd1d94654659cd35192ee4c913bb7b702d963 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 28 Feb 2020 17:31:25 -0500 Subject: [PATCH 26/86] 0.14.0 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 5698d87a8..b1944a041 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 14 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 404658416f2df109b2547165087ad3e6f7c12fdf Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 4 Mar 2020 16:07:44 -0500 Subject: [PATCH 27/86] 0.15.0 version bump. --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index d1db7e339..bea17c26c 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 14 -PATCH_VERSION = "1.dev0" +MINOR_VERSION = 15 +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From bb88dfa8a520be43f3f3c8b62e959ffbfac0af71 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 8 Mar 2020 22:23:09 -0400 Subject: [PATCH 28/86] 0.16.0 version bump. --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index e0371ee03..0bc2414b1 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 15 -PATCH_VERSION = "1.dev0" +MINOR_VERSION = 16 +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 90bd300b16bb93ae1516b9622645a465a7ce2479 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 26 Mar 2020 22:56:07 -0400 Subject: [PATCH 29/86] 0.17.0 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index fb86f18a4..00ab531e3 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 17 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 53f1a197221c1e08dec72c0cbef12dfced47794e Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 27 Mar 2020 10:26:53 -0400 Subject: [PATCH 30/86] Fix PyPa workflow --- .github/workflows/publish-to-pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-to-pypi.yml b/.github/workflows/publish-to-pypi.yml index 0ac145e63..6d0e1839c 100644 --- a/.github/workflows/publish-to-pypi.yml +++ b/.github/workflows/publish-to-pypi.yml @@ -21,6 +21,6 @@ jobs: run: >- python3 setup.py sdist bdist_wheel - name: Publish distribution to PyPI - uses: pypa/gh-action-pypi-publish@test-master + uses: pypa/gh-action-pypi-publish@master with: password: ${{ secrets.PYPI_TOKEN }} From d2ea5bf919b41b980573972311f3a88660ac0417 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 31 Mar 2020 22:19:12 -0400 Subject: [PATCH 31/86] 0.18.0 Version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 259b173bf..64994a5c3 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 18 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From f222311f0fa941b2b0027525726a534890d15a0f Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 4 Apr 2020 11:29:06 -0400 Subject: [PATCH 32/86] 0.18.1 version bump. --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index da694ac0d..dbfeab569 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 19 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 18 +PATCH_VERSION = "1" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 2cfb687b64afe8a2324e9e72fe9661c14c98573f Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 8 Apr 2020 20:08:11 -0400 Subject: [PATCH 33/86] 0.18.2 version bump. --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index da694ac0d..4765bb2b8 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 19 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 18 +PATCH_VERSION = "2" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 54972b82f0c06dcd985978c2b282001a8d28a9f8 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 10 Apr 2020 21:16:48 -0400 Subject: [PATCH 34/86] 0.19.0 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index da694ac0d..bbffbdf61 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 19 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 054fec57681f3da03c537413c05ab48e0f5ac26b Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 15 Apr 2020 17:23:22 -0400 Subject: [PATCH 35/86] 0.20.0 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 191ce683e..2f5f4894c 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 20 -PATCH_VERSION = "a2" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From f60a522da463d631d55687000ae4eefdceca801c Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 2 May 2020 22:18:26 -0400 Subject: [PATCH 36/86] 0.20.1 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index ed0995ba8..24e0dd60c 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 20 -PATCH_VERSION = "1.a3" +PATCH_VERSION = "1" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 2d3b7925c79f621b52fa068dc007c7d2fbd618cd Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Mon, 11 May 2020 15:38:42 -0400 Subject: [PATCH 37/86] 0.20.2 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 24d65a18f..105ba6347 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 20 -PATCH_VERSION = "2.dev0" +PATCH_VERSION = "2" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From c299ec33fb086c2fabfe3a74584b52b009d77edc Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Mon, 11 May 2020 17:57:43 -0400 Subject: [PATCH 38/86] 0.20.3 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 6dc11de5d..7bf0fd147 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 20 -PATCH_VERSION = "3.dev0" +PATCH_VERSION = "3" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 3f8871756d939c5a6360c3d8c0dfb672bd10dfc4 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 16 May 2020 13:08:41 -0400 Subject: [PATCH 39/86] 0.20.4 version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index e4b818c3a..074e8440c 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 20 -PATCH_VERSION = "4.dev0" +PATCH_VERSION = "4" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 649efb3097087c8939e84864cab892ff7ec5629b Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 5 Jun 2020 19:29:28 -0400 Subject: [PATCH 40/86] 0.21.0 Version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 964a327d2..88c56dc0f 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 20 -PATCH_VERSION = "5.dev0" +MINOR_VERSION = 21 +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From fab494f1c02b05574a2efdf2079bbaa21436943d Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Mon, 6 Jul 2020 16:35:50 -0400 Subject: [PATCH 41/86] 0.22.0 version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index f053f56e8..b39f0b03e 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 21 -PATCH_VERSION = "1.dev0" +MINOR_VERSION = 22 +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 10d5084e340ffd825744ab8329a36fa7ff447ff4 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 10 Jul 2020 16:23:50 -0400 Subject: [PATCH 42/86] 0.22.1 version bump. --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 791b9aad4..88098fcd3 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 23 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 22 +PATCH_VERSION = "1" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From dbc4e1b65559d799e8fc5b611e5df2b7dcd24fad Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 16 Jul 2020 14:01:43 -0400 Subject: [PATCH 43/86] 0.22.2 version bump. --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 791b9aad4..46885894a 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 23 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 22 +PATCH_VERSION = "2" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 6828acee9f9d09fd2e13d01985139064970ea49b Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 1 Sep 2020 21:47:28 -0400 Subject: [PATCH 44/86] 0.23.0 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 791b9aad4..be1372c3a 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 23 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From fb76eee986d9d36e537134b9b5c8c330aa330880 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 5 Sep 2020 14:08:20 -0400 Subject: [PATCH 45/86] 0.23.1 version bump. --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index e2f18c446..0acf351fd 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 24 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 23 +PATCH_VERSION = "1" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 87c3dfaab1bad49ce6b2efff2959984efec30378 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 9 Sep 2020 13:21:10 -0400 Subject: [PATCH 46/86] 0.23.2 version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index e2f18c446..9812ddb7f 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 24 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 23 +PATCH_VERSION = "2" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 8615261cb596aa4181d8a821817cc4a227bf6665 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 16 Sep 2020 16:42:47 -0400 Subject: [PATCH 47/86] 0.24.0 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index e2f18c446..9d32b785a 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 24 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 363994527331f7320b8d7fc8dfef5b6ce7545e35 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 18 Sep 2020 21:20:40 -0400 Subject: [PATCH 48/86] 0.24.1 version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 3c3e70cb0..07bb4e8cc 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 25 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 24 +PATCH_VERSION = "1" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 41fd6b72bcbe692eb33040d16081463a928b5202 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 27 Sep 2020 13:24:49 -0400 Subject: [PATCH 49/86] 0.24.2 version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 3c3e70cb0..000a8fbf8 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 25 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 24 +PATCH_VERSION = "2" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From e68b65b0633a85bf37658466f9d33349080b6afa Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 27 Sep 2020 21:46:29 -0400 Subject: [PATCH 50/86] 0.24.3 version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 3c3e70cb0..d85e0318f 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 25 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 24 +PATCH_VERSION = "3" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From cf8fc9ae5df790a17f8e69d6a2d2310614f4d7d9 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 30 Sep 2020 19:18:58 -0400 Subject: [PATCH 51/86] 0.25.0 Version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 3c3e70cb0..abab97f35 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 25 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From fc128b84ed6d5e5e5283767ab994be4cd2282c05 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 6 Oct 2020 18:08:06 -0400 Subject: [PATCH 52/86] 0.26.0 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 1814b67e8..9ae890843 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 26 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) From 30d76354d61effbf11efdb14ae8794fc206522ec Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 31 Oct 2020 12:03:03 -0400 Subject: [PATCH 53/86] 0.27.0 Version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 82c6b36a2..0a1bb289f 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 27 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 6038643ac9f522081970a5bf5d52450838c64163 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 18 Nov 2020 19:57:24 -0500 Subject: [PATCH 54/86] 0.27.1 version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 96e2ceb27..e74e5b60f 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 28 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 27 +PATCH_VERSION = "1" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 800630a38a2c00a2630710b0cf6a17b213174225 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 20 Nov 2020 19:15:57 -0500 Subject: [PATCH 55/86] Bump up version to 0.28.0 --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 96e2ceb27..ca1204fb7 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 28 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 46dedaf30955629f7cb2268c79a52bece24088af Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 24 Nov 2020 15:50:22 -0500 Subject: [PATCH 56/86] 0.28.1 version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 1ef9c8d7d..f4e6edf6a 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 29 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 28 +PATCH_VERSION = "1" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 29887d74065674f89beba3c6130c3a8228bdf388 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Mon, 7 Dec 2020 15:19:15 -0500 Subject: [PATCH 57/86] 0.28.2 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index f4e6edf6a..590c8a0c5 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 28 -PATCH_VERSION = "1" +PATCH_VERSION = "2" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 89541814d899b8d47cba43d8a3ccfad24a35886b Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 30 Dec 2020 10:56:35 -0500 Subject: [PATCH 58/86] 0.29.0 Version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 1ef9c8d7d..60e299ced 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 29 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 2afea32fd26ce19639874108ae63dee60f71b522 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 16 Jan 2021 11:58:03 -0500 Subject: [PATCH 59/86] 0.30.0 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 7d08e2d4e..0582378f9 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 30 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 17c8a0d56d8bd2a1e5165bd59158541c25d1c662 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 19 Jan 2021 13:23:55 -0500 Subject: [PATCH 60/86] 0.30.1 version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index c53cb2ac7..34e4b93d1 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 31 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 30 +PATCH_VERSION = "1" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From aecbfda78d29a2482800f5dd7af12e83d542d1b4 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 20 Jan 2021 17:07:47 -0500 Subject: [PATCH 61/86] 0.31.0 Version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index c53cb2ac7..2c20c3153 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 31 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 43166bedc705337ed03f8f204cd68f66cd7bc747 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Mon, 25 Jan 2021 19:38:58 -0500 Subject: [PATCH 62/86] 0.32.0 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index f1ad62456..85189a16a 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 32 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From f5371c31f879dd8b44234140136f4d4d6f993a1d Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 5 Mar 2021 14:45:51 -0500 Subject: [PATCH 63/86] 0.33.0 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index f81c479db..4002cf353 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 33 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From f1860a1cabc29dbe2ea83596ba28ace86944f9bf Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 11 Jun 2021 19:59:30 -0400 Subject: [PATCH 64/86] 0.34.0 Version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 27aedcf8e..bf9761067 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 34 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From dd2769017bd3f7b72fc269f5bf851944e21b805c Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 30 Jun 2021 19:06:19 -0400 Subject: [PATCH 65/86] 0.35.0 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 9c0f6d9ae..3550e9701 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 35 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From ddd5b53dfc8a4ffd605284598b8d421aa762fd08 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Mon, 5 Jul 2021 12:55:54 -0400 Subject: [PATCH 66/86] 0.35.1 Version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index a38ba00a2..84d5024bc 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 36 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 35 +PATCH_VERSION = "1" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 6d56190b8cc48e661f04a751863e115d165c4ebb Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 9 Jul 2021 18:29:23 -0400 Subject: [PATCH 67/86] 0.35.2 Version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index a38ba00a2..3675cb581 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 36 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 35 +PATCH_VERSION = "2" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 6d907802fc8710723e3a800d87dc763e2ab8516a Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 24 Jul 2021 23:51:30 -0400 Subject: [PATCH 68/86] 0.36.0 Version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index a38ba00a2..35d6e9c79 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 36 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 42ae9868484be781ee73b3b3f05c25d5fd47a317 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 29 Jul 2021 18:07:20 -0400 Subject: [PATCH 69/86] 0.36.1 Version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 6d0835a25..7e5c97657 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 37 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 36 +PATCH_VERSION = "1" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 58d66f8e74bb89700b56764ac91e0207655a6a48 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 11 Aug 2021 21:01:26 -0400 Subject: [PATCH 70/86] 0.36.2 Version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 6d0835a25..b967ec33f 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 37 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 36 +PATCH_VERSION = "2" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 2c4f0fd0c1eb9027ad6dc44a729785480845fdab Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 22 Aug 2021 16:54:16 -0400 Subject: [PATCH 71/86] 0.37.0 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 6d0835a25..7d0dfc231 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 37 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 298df7fa6b3906e03c4a374a0b2ef6b56c74c263 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 24 Aug 2021 22:29:32 -0400 Subject: [PATCH 72/86] 0.37.1 version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 8572f57d0..00aa5bef4 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 -MINOR_VERSION = 38 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 37 +PATCH_VERSION = "1" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From d1252652bde0ac8ce33c0cd619328047f46ee93a Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Wed, 1 Sep 2021 22:14:57 -0400 Subject: [PATCH 73/86] Fix Ledvance OTA by accounting for new JSON version keys (#801) * Fix Ledvance OTA by accounting for new JSON version keys Fixes #800 * Clarify `LedvanceImage` arguments --- tests/test_ota_provider.py | 18 ++++++++++++++---- zigpy/ota/provider.py | 22 +++++++++++++++------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/tests/test_ota_provider.py b/tests/test_ota_provider.py index 96b498aa3..ec352b45d 100644 --- a/tests/test_ota_provider.py +++ b/tests/test_ota_provider.py @@ -655,7 +655,12 @@ async def test_ledvance_refresh_list( "identity": { "company": 4489, "product": 25, - "version": {"major": 1, "minor": 2, "build": 428}, + "version": { + "major": 1, + "minor": 2, + "build": 428, + "revision": 40, + }, }, "releaseNotes": "", "shA256": sha_1, @@ -672,7 +677,12 @@ async def test_ledvance_refresh_list( "identity": { "company": 4489, "product": 13, - "version": {"major": 1, "minor": 2, "build": 428}, + "version": { + "major": 1, + "minor": 2, + "build": 428, + "revision": 40, + }, }, "releaseNotes": "", "shA256": sha_2, @@ -699,11 +709,11 @@ async def test_ledvance_refresh_list( cached_1 = ledvance_prov._cache[img1.key] assert cached_1.image_type == img1.image_type base = "https://api.update.ledvance.com/v1/zigbee/firmwares/download" - assert cached_1.url == base + "?Company=4489&Product=25&Version=1.2.428" + assert cached_1.url == base + "?Company=4489&Product=25&Version=1.2.428.40" cached_2 = ledvance_prov._cache[img2.key] assert cached_2.image_type == img2.image_type - assert cached_2.url == base + "?Company=4489&Product=13&Version=1.2.428" + assert cached_2.url == base + "?Company=4489&Product=13&Version=1.2.428.40" assert not ledvance_prov.expired diff --git a/zigpy/ota/provider.py b/zigpy/ota/provider.py index 076e7084a..1f930d79f 100644 --- a/zigpy/ota/provider.py +++ b/zigpy/ota/provider.py @@ -7,6 +7,7 @@ import os import os.path from typing import Dict, Optional +import urllib.parse import aiohttp import attr @@ -195,17 +196,24 @@ class LedvanceImage: @classmethod def new(cls, data): - ident = data["identity"] - company, product, ver = (ident["company"], ident["product"], ident["version"]) - major, minor, build = (ver["major"], ver["minor"], ver["build"]) + identity = data["identity"] + ver = identity["version"] - res = cls(company, product) + res = cls(manufacturer_id=identity["company"], image_type=identity["product"]) res.file_version = int(data["fullName"].split("/")[1], 16) res.image_size = data["length"] - res.url = ( - f"https://api.update.ledvance.com/v1/zigbee/firmwares/download" - f"?Company={company}&Product={product}&Version={major}.{minor}.{build}" + "https://api.update.ledvance.com/v1/zigbee/firmwares/download?" + + urllib.parse.urlencode( + { + "Company": identity["company"], + "Product": identity["product"], + "Version": ( + f"{ver['major']}.{ver['minor']}" + f".{ver['build']}.{ver['revision']}" + ), + } + ) ) return res From 9d7848fd0ae632695c8dfd93684194f2e69152d1 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 2 Sep 2021 20:24:38 -0400 Subject: [PATCH 74/86] 0.37.2 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 00aa5bef4..c95b6c7c1 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 37 -PATCH_VERSION = "1" +PATCH_VERSION = "2" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 2323190879dceaa9c56bc2934837526ce4b63c2a Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 2 Sep 2021 20:40:55 -0400 Subject: [PATCH 75/86] 0.38.0 Version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 8572f57d0..5a6b7f038 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 38 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 0f62259bab4dbf1a6a0dcb4c0b2be8febaa1cb27 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 24 Oct 2021 21:19:36 -0400 Subject: [PATCH 76/86] 0.39.0 version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index bb02948b7..a64767ee4 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 39 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From ce0e5cdba5d7030057d77e78f8d943f743dac85e Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Thu, 28 Oct 2021 20:08:02 -0400 Subject: [PATCH 77/86] 0.40.0 Version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 7058b254a..169136084 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 40 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 6a38f49fe6a6a973bf987f73a272b4be951e35df Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sun, 7 Nov 2021 16:39:07 -0500 Subject: [PATCH 78/86] 0.41.0 Version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index b73df6ae1..5476e5d46 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 41 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 5c2d0bbe5af46bceccf342c4136dab8ef2de9998 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 1 Dec 2021 19:56:35 -0500 Subject: [PATCH 79/86] 0.42.0 Version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index da2f75153..97d74b410 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 42 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From e266d11275b5513eb397d33f357c17859f656e81 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 21 Jan 2022 19:30:56 -0500 Subject: [PATCH 80/86] 0.43.0 Version bump. --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 1876b1d0d..d3c6a4354 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,6 +1,6 @@ # coding: utf-8 MAJOR_VERSION = 0 MINOR_VERSION = 43 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 6c48d536ddfa33c58220fe68ba0fa10e34b09e03 Mon Sep 17 00:00:00 2001 From: MDW Date: Sat, 22 Jan 2022 01:43:49 +0100 Subject: [PATCH 81/86] #873 Add write_attributes_raw method (#887) * Add write_attributes_raw method Enables writing attributes that are not predefined. Similar to read_attributes_raw * Alphabetical order for radios * Better argument name for write_attributes_raw * Need await on write_attributes_raw call * Renamed other occurences of 'args' * Try multiple mock patch to catch uppermost exception * Adjusted test to detect exception, also test other method * Removed dual mock test * Renamed args to attrs in write_attributes --- README.md | 2 +- tests/test_zcl.py | 16 ++++++++++++++++ zigpy/zcl/__init__.py | 15 +++++++++++---- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 654add87c..2467c0a23 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,8 @@ Older packages of tagged versions are still available on the "zigpy-homeassistan Packages of tagged versions of the radio libraries are released via separate projects on PyPI - https://pypi.org/project/zigpy/ - https://pypi.org/project/bellows/ - - https://pypi.org/project/zigpy-deconz/ - https://pypi.org/project/zigpy-cc/ + - https://pypi.org/project/zigpy-deconz/ - https://pypi.org/project/zigpy-xbee/ - https://pypi.org/project/zigpy-zigate/ - https://pypi.org/project/zigpy-znp/ diff --git a/tests/test_zcl.py b/tests/test_zcl.py index a461cd8f0..a969229aa 100644 --- a/tests/test_zcl.py +++ b/tests/test_zcl.py @@ -388,12 +388,28 @@ async def test_write_wrong_attribute(cluster): assert cluster._write_attributes.call_count == 1 +async def test_write_unknown_attribute(cluster): + with patch.object(cluster, "_write_attributes", new=AsyncMock()): + with pytest.raises(KeyError): + # Using an invalid attribute name, the call should fail + await cluster.write_attributes({"dummy_attribute": 5}) + assert cluster._write_attributes.call_count == 0 + + async def test_write_attributes_wrong_type(cluster): with patch.object(cluster, "_write_attributes", new=AsyncMock()): await cluster.write_attributes({18: 0x2222}) assert cluster._write_attributes.call_count == 1 +async def test_write_attributes_raw(cluster): + with patch.object(cluster, "_write_attributes", new=AsyncMock()): + # write_attributes_raw does not check the attributes, + # send to unknown attribute in cluster, the write should be effective + await cluster.write_attributes_raw({0: 5, 0x3000: 5}) + assert cluster._write_attributes.call_count == 1 + + @pytest.mark.parametrize( "cluster_id, attr, value, serialized", ( diff --git a/zigpy/zcl/__init__.py b/zigpy/zcl/__init__.py index 2357f18fd..7fc3309ce 100644 --- a/zigpy/zcl/__init__.py +++ b/zigpy/zcl/__init__.py @@ -374,18 +374,25 @@ def _write_attr_records( async def write_attributes( self, attributes: Dict[Union[str, int], Any], manufacturer: Optional[int] = None ) -> List: - args = self._write_attr_records(attributes) - result = await self._write_attributes(args, manufacturer=manufacturer) + """Write attributes to device with internal 'attributes' validation""" + attrs = self._write_attr_records(attributes) + return await self.write_attributes_raw(attrs, manufacturer) + + async def write_attributes_raw( + self, attrs: List[foundation.Attribute], manufacturer: Optional[int] = None + ) -> List: + """Write attributes to device without internal 'attributes' validation""" + result = await self._write_attributes(attrs, manufacturer=manufacturer) if not isinstance(result[0], list): return result records = result[0] if len(records) == 1 and records[0].status == foundation.Status.SUCCESS: - for attr_rec in args: + for attr_rec in attrs: self._attr_cache[attr_rec.attrid] = attr_rec.value.value else: failed = [rec.attrid for rec in records] - for attr_rec in args: + for attr_rec in attrs: if attr_rec.attrid not in failed: self._attr_cache[attr_rec.attrid] = attr_rec.value.value From d77dd906f2a233caac512eb4b68681c106222609 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Wed, 30 Mar 2022 11:50:28 -0400 Subject: [PATCH 82/86] 0.44.0 Version bump --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 9270960d4..65deb9085 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 MINOR_VERSION = 44 -PATCH_VERSION = "0.dev0" +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 961e0cd315155ce4fba47aaaf39e4a7054030946 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Wed, 30 Mar 2022 12:54:06 -0400 Subject: [PATCH 83/86] Bump patch version to 0.44.1 --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 65deb9085..4e4c8c6f9 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 MINOR_VERSION = 44 -PATCH_VERSION = "0" +PATCH_VERSION = "1" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From ce066dedcf3133f66c7e7e42913351ef9fd46f4d Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Wed, 30 Mar 2022 12:54:06 -0400 Subject: [PATCH 84/86] Bump patch version to 0.44.1 --- zigpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 65deb9085..4e4c8c6f9 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 MINOR_VERSION = 44 -PATCH_VERSION = "0" +PATCH_VERSION = "1" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 53813f94bdcd9fab90e5cd3e8f1209deb8a1c6e8 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Sun, 10 Apr 2022 19:09:48 -0400 Subject: [PATCH 85/86] 0.44.2 Release --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index 2fa1947b5..e6e2644fe 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 -MINOR_VERSION = 45 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 44 +PATCH_VERSION = "2" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" From 7807afeb449387f8c2835f581e56d45debbc1477 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Tue, 26 Apr 2022 17:42:26 -0400 Subject: [PATCH 86/86] 0.45.0 version bump --- zigpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zigpy/__init__.py b/zigpy/__init__.py index e6e2644fe..a668ef1b5 100644 --- a/zigpy/__init__.py +++ b/zigpy/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 -MINOR_VERSION = 44 -PATCH_VERSION = "2" +MINOR_VERSION = 45 +PATCH_VERSION = "0" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}"