Skip to content

Commit

Permalink
fix zigbee groups, updates form zigbee-herdsman (#60)
Browse files Browse the repository at this point in the history
* pull updates from zigbee-herdsman
fix zigbee groups fixes #58

* add test

* update broadcast based on zigbee-herdsman

* ignore resetInd, do not log waiting for...
  • Loading branch information
sanyatuning committed Aug 13, 2020
1 parent 9413973 commit 5625ea5
Show file tree
Hide file tree
Showing 17 changed files with 391 additions and 236 deletions.
4 changes: 2 additions & 2 deletions setup.py
Expand Up @@ -17,8 +17,8 @@
"Texas Instruments CC2531 radios for zigpy",
long_description=long_description,
long_description_content_type="text/markdown",
url="http://github.com/sanyatuning/zigpy-cc",
author="Balázs Sándor",
url="http://github.com/zigpy/zigpy-cc",
author="Balazs Sandor",
author_email="sanyatuning@gmail.com",
license="GPL-3.0",
packages=find_packages(exclude=["*.tests"]),
Expand Down
9 changes: 7 additions & 2 deletions test.py
Expand Up @@ -3,15 +3,20 @@
import os

import coloredlogs as coloredlogs
from zigpy_cc import config
import zigpy.config
from zigpy.device import Device

from zigpy_cc import config
from zigpy_cc.zigbee import application

fmt = "%(name)s %(levelname)s %(message)s"
coloredlogs.install(level="DEBUG", fmt=fmt)

APP_CONFIG = {
zigpy.config.CONF_NWK: {
zigpy.config.CONF_NWK_PAN_ID: 0x2A61,
zigpy.config.CONF_NWK_EXTENDED_PAN_ID: "A0:B0:C0:D0:10:20:30:40",
},
config.CONF_DEVICE: {
config.CONF_DEVICE_PATH: "auto",
config.CONF_DEVICE_BAUDRATE: 115200,
Expand Down Expand Up @@ -80,7 +85,7 @@ async def main():
await app.startup(auto_form=False)
await app.form_network()

# await app.permit_ncp()
await app.permit_ncp()


loop.run_until_complete(main())
Expand Down
4 changes: 2 additions & 2 deletions tests/test_api.py
Expand Up @@ -81,7 +81,7 @@ async def mock_fut():

for subsystem, commands in Definition.items():
for cmd in commands:
ret = await api._command(subsystem, cmd["name"], mock.sentinel.cmd_data)
ret = await api.request(subsystem, cmd["name"], mock.sentinel.cmd_data)
assert ret is mock.sentinel.cmd_result
# assert api._api_frame.call_count == 1
# assert api._api_frame.call_args[0][0] == cmd
Expand Down Expand Up @@ -111,7 +111,7 @@ def mock_obj(subsystem, command, payload):
for subsystem, commands in Definition.items():
for cmd in commands:
with pytest.raises(asyncio.TimeoutError):
await api._command(subsystem, cmd["name"], mock.sentinel.cmd_data)
await api.request(subsystem, cmd["name"], mock.sentinel.cmd_data)
# assert api._api_frame.call_count == 1
# assert api._api_frame.call_args[0][0] == cmd
# assert api._api_frame.call_args[0][1] == mock.sentinel.cmd_data
Expand Down
84 changes: 49 additions & 35 deletions tests/test_application.py
Expand Up @@ -3,8 +3,9 @@
from unittest import mock

import pytest
from zigpy.types import EUI64
from zigpy.types import EUI64, Group, BroadcastAddress
import zigpy.zdo.types as zdo_t
from zigpy.zcl.clusters.general import Groups

from zigpy_cc import types as t
from zigpy_cc.api import API
Expand All @@ -26,6 +27,7 @@ def app():
app = application.ControllerApplication(APP_CONFIG)
app._api = API(APP_CONFIG[config.CONF_DEVICE])
app._api.set_application(app)
app._semaphore = asyncio.Semaphore()
return app


Expand Down Expand Up @@ -64,39 +66,6 @@ def addr_nwk_and_ieee(nwk, ieee):
return addr


"""
DEBUG:zigpy_cc.api:--> AREQ ZDO leaveInd {'srcaddr': 406, 'extaddr': '0x07a3c302008d1500', 'request': 0, 'removechildren': 0, 'rejoin': 0}
DEBUG:zigpy_cc.api:--> AREQ ZDO tcDeviceInd {'nwkaddr': 11938, 'extaddr': '0x07a3c302008d1500', 'parentaddr': 0}
DEBUG:zigpy_cc.api:--> AREQ ZDO endDeviceAnnceInd {'srcaddr': 11938, 'nwkaddr': 11938, 'ieeeaddr': '0x07a3c302008d1500', 'capabilities': 128}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 0, 'srcaddr': 11938, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 123, 'securityuse': 0, 'timestamp': 1000027, 'transseqnumber': 0, 'len': 25, 'data': bytearray(b'\x18\x00\n\x05\x00B\x12lumi.sensor_switch')}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 0, 'srcaddr': 11938, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 123, 'securityuse': 0, 'timestamp': 1000039, 'transseqnumber': 0, 'len': 7, 'data': bytearray(b'\x18\x01\n\x01\x00 \n')}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 0, 'srcaddr': 11938, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 126, 'securityuse': 0, 'timestamp': 1000050, 'transseqnumber': 0, 'len': 29, 'data': bytearray(b'\x1c4\x12\x02\n\x02\xffL\x06\x00\x10\x01!\xd8\x0b!\xa8\x01$\x00\x00\x00\x00\x00!\xbdJ Y')}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 6595, 'relaycount': 1, 'relaylist': [30485]}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 10, 'srcaddr': 6595, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 60, 'securityuse': 0, 'timestamp': 1069473, 'transseqnumber': 0, 'len': 5, 'data': bytearray(b'\x10\x94\x00\x00\x00')}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 49164, 'relaycount': 2, 'relaylist': [6595, 30485]}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 10, 'srcaddr': 49164, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 60, 'securityuse': 0, 'timestamp': 1117084, 'transseqnumber': 0, 'len': 5, 'data': bytearray(b'\x10\x13\x00\x00\x00')}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 51918, 'relaycount': 0, 'relaylist': []}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 51918, 'relaycount': 0, 'relaylist': []}
DEBUG:zigpy_cc.api:--> AREQ ZDO endDeviceAnnceInd {'srcaddr': 53322, 'nwkaddr': 53322, 'ieeeaddr': '0x41e54b02008d1500', 'capabilities': 132}
DEBUG:zigpy_cc.api:--> AREQ ZDO tcDeviceInd {'nwkaddr': 53322, 'extaddr': '0x41e54b02008d1500', 'parentaddr': 51918}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 53322, 'relaycount': 1, 'relaylist': [51918]}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 10, 'srcaddr': 53322, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 39, 'securityuse': 0, 'timestamp': 1137608, 'transseqnumber': 0, 'len': 5, 'data': bytearray(b'\x10\x1d\x00\x00\x00')}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 44052, 'relaycount': 2, 'relaylist': [6595, 30485]}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 18, 'srcaddr': 44052, 'srcendpoint': 2, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 60, 'securityuse': 0, 'timestamp': 1167545, 'transseqnumber': 0, 'len': 8, 'data': bytearray(b'\x18E\nU\x00!\x02\x00')}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 6595, 'relaycount': 1, 'relaylist': [30485]}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 10, 'srcaddr': 6595, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 57, 'securityuse': 0, 'timestamp': 1256953, 'transseqnumber': 0, 'len': 5, 'data': bytearray(b'\x10\xd1\x00\x00\x00')}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 49164, 'relaycount': 2, 'relaylist': [6595, 30485]}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 10, 'srcaddr': 49164, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 57, 'securityuse': 0, 'timestamp': 1310524, 'transseqnumber': 0, 'len': 5, 'data': bytearray(b'\x10\x14\x00\x00\x00')}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 53322, 'relaycount': 1, 'relaylist': [51918]}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 10, 'srcaddr': 53322, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 39, 'securityuse': 0, 'timestamp': 1331211, 'transseqnumber': 0, 'len': 5, 'data': bytearray(b'\x10\x1e\x00\x00\x00')}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 6595, 'relaycount': 1, 'relaylist': [30485]}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 10, 'srcaddr': 6595, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 60, 'securityuse': 0, 'timestamp': 1444466, 'transseqnumber': 0, 'len': 5, 'data': bytearray(b'\x10\x0e\x00\x00\x00')}
DEBUG:zigpy_cc.api:--> AREQ ZDO srcRtgInd {'dstaddr': 49164, 'relaycount': 2, 'relaylist': [6595, 30485]}
DEBUG:zigpy_cc.api:--> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 10, 'srcaddr': 49164, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 57, 'securityuse': 0, 'timestamp': 1504140, 'transseqnumber': 0, 'len': 5, 'data': bytearray(b'\x10\x15\x00\x00\x00')}
DEBUG:zigpy_cc.api:--> AREQ ZDO tcDeviceInd {'nwkaddr': 49164, 'extaddr': '0x7ceb2303008d1500', 'parentaddr': 6595}
"""


def test_join(app):
payload = {"nwkaddr": 27441, "extaddr": "0x07a3c302008d1500", "parentaddr": 0}
obj = ZpiObject(2, 5, "tcDeviceInd", 202, payload, [])
Expand Down Expand Up @@ -199,13 +168,58 @@ async def test_request(app: application.ControllerApplication):
)

assert len(app._api._waiters) == 1
assert (
"SREQ ZDO nodeDescReq tsn: 1 {'dstaddr': 0xd04a, 'nwkaddrofinterest': 0x2ea2}"
== str(app._api.request_raw.call_args[0][0])
)
assert res == (0, "message send success")


@pytest.mark.asyncio
async def test_mrequest(app: application.ControllerApplication):
fut = asyncio.Future()
fut.set_result(None)
app._api.request_raw = mock.MagicMock(return_value=fut)

# multicast (0x0002, 260, 6, 1, 39, b"\x01'\x00", 0, 3)
res = await app.mrequest(Group(2), 260, Groups.cluster_id, 1, 39, b"\x01'\x00")

assert 1 == len(app._api._waiters)
assert (
"SREQ AF dataRequestExt tsn: 39 {'dstaddrmode': <AddressMode.ADDR_GROUP: 1>, "
"'dstaddr': 0x0002, 'destendpoint': 255, 'dstpanid': 0, "
"'srcendpoint': 1, 'clusterid': 4, 'transid': 39, 'options': 0, 'radius': 30, 'len': 3, "
"'data': b\"\\x01'\\x00\"}" == str(app._api.request_raw.call_args[0][0])
)
assert (0, "message send success") == res


@pytest.mark.asyncio
async def test_broadcast(app: application.ControllerApplication):
fut = asyncio.Future()
fut.set_result(None)
app._api.request_raw = mock.MagicMock(return_value=fut)

# broadcast (0, 54, 0, 0, 0, 0, 45, b'-<\x00', <BroadcastAddress.ALL_ROUTERS_AND_COORDINATOR: 65532>)
res = await app.broadcast(
0, 54, 0, 0, 0, 0, 45, b"-<\x00", BroadcastAddress.ALL_ROUTERS_AND_COORDINATOR
)

assert 0 == len(app._api._waiters)
assert (
"SREQ ZDO mgmtPermitJoinReq tsn: 45 {'addrmode': <AddressMode.ADDR_BROADCAST: 15>, "
"'dstaddr': 0xfffc, 'duration': 60, 'tcsignificance': 0}"
== str(app._api.request_raw.call_args[0][0])
)
assert (0, "broadcast send success") == res


"""
zigpy_cc.api DEBUG <-- SREQ ZDO nodeDescReq {'dstaddr': 53322, 'nwkaddrofinterest': 0}
zigpy_cc.api DEBUG --> SRSP ZDO nodeDescReq {'status': 0}
zigpy_cc.api DEBUG --> AREQ ZDO nodeDescRsp {'srcaddr': 53322, 'status': 128, 'nwkaddr': 0, 'logicaltype_cmplxdescavai_userdescavai': 0, 'apsflags_freqband': 0, 'maccapflags': 0, 'manufacturercode': 0, 'maxbuffersize': 0, 'maxintransfersize': 0, 'servermask': 0, 'maxouttransfersize': 0, 'descriptorcap': 0}
zigpy_cc.api DEBUG --> AREQ ZDO nodeDescRsp {'srcaddr': 53322, 'status': 128, 'nwkaddr': 0,
'logicaltype_cmplxdescavai_userdescavai': 0, 'apsflags_freqband': 0, 'maccapflags': 0, 'manufacturercode': 0,
'maxbuffersize': 0, 'maxintransfersize': 0, 'servermask': 0, 'maxouttransfersize': 0, 'descriptorcap': 0}
"""


Expand Down
16 changes: 11 additions & 5 deletions tests/test_buffalo.py
@@ -1,6 +1,6 @@
import zigpy_cc.types as t
from zigpy.types import EUI64, NWK
from zigpy.types import EUI64, Group, NWK

import zigpy_cc.types as t
from zigpy_cc.buffalo import Buffalo, BuffaloOptions

ieeeAddr1 = {
Expand All @@ -26,15 +26,21 @@ def test_write_ieee2():
assert ieeeAddr2["hex"] == data_out.buffer


def test_write_ieee_group():
data_out = Buffalo(b"")
data_out.write_parameter(t.ParameterType.IEEEADDR, Group(2), {})
assert b"\x02\x00\x00\x00\x00\x00\x00\x00" == data_out.buffer


def test_read_ieee():
data_in = Buffalo(ieeeAddr1["hex"])
actual = data_in.read_parameter(t.ParameterType.IEEEADDR, {})
actual = data_in.read_parameter("test", t.ParameterType.IEEEADDR, {})
assert ieeeAddr1["string"] == actual


def test_read_ieee2():
data_in = Buffalo(ieeeAddr2["hex"])
actual = data_in.read_parameter(t.ParameterType.IEEEADDR, {})
actual = data_in.read_parameter("test", t.ParameterType.IEEEADDR, {})
assert ieeeAddr2["string"] == actual


Expand Down Expand Up @@ -62,5 +68,5 @@ def test_list_nighbor_lqi():
data_in = Buffalo(data_out.buffer)
options = BuffaloOptions()
options.length = len(value)
act = data_in.read_parameter(t.ParameterType.LIST_NEIGHBOR_LQI, options)
act = data_in.read_parameter("test", t.ParameterType.LIST_NEIGHBOR_LQI, options)
assert value == act
17 changes: 9 additions & 8 deletions tests/test_types.py
Expand Up @@ -305,7 +305,7 @@ def test_ieee_addr():
def test_from_cluster_id():
profile = 0
obj = ZpiObject.from_cluster(
NWK(53322), profile, ZDOCmd.Node_Desc_req, 0, 0, 3, b"\x03\x4a\xd0", 32
NWK(53322), profile, ZDOCmd.Node_Desc_req, 0, 0, 3, b"\x03\x4a\xd0"
)

assert (
Expand All @@ -327,11 +327,11 @@ def test_from_cluster_id():
def test_from_cluster_id_ZCL():
profile = 260
obj = ZpiObject.from_cluster(
NWK(53322), profile, 0, 1, 1, 1, b"\x00\x0b\x00\x04\x00\x05\x00", 123
NWK(53322), profile, 0, 1, 1, 123, b"\x00\x0b\x00\x04\x00\x05\x00"
)

assert (
"SREQ AF dataRequest tsn: 1 {'dstaddr': 53322, 'destendpoint': 1, "
"SREQ AF dataRequest tsn: 123 {'dstaddr': 53322, 'destendpoint': 1, "
"'srcendpoint': 1, 'clusterid': 0, 'transid': 123, 'options': 0, 'radius': 30, "
"'len': 7, 'data': b'\\x00\\x0b\\x00\\x04\\x00\\x05\\x00'}" == str(obj)
)
Expand Down Expand Up @@ -368,23 +368,24 @@ def test_bind_req():
b"\x01<x'\xfe\xffW\x0b\x00\x01\x08\x00\x03\x0c%\xed\x18\x00K\x12\x00\x01", True, False)
zigpy_cc.api DEBUG waiting for 1 bindReq
zigpy_cc.api DEBUG --> SREQ ZDO bindReq tsn: 1 {
'dstaddr': 0xbd8b, 'srcaddr': 00:0b:57:ff:fe:27:78:3c, 'srcendpoint': 1, 'clusterid': 8, 'dstaddrmode': 3, 'dstaddress': 00:12:4b:00:18:ed:25:0c, 'dstendpoint': 1}
'dstaddr': 0xbd8b, 'srcaddr': 00:0b:57:ff:fe:27:78:3c, 'srcendpoint': 1, 'clusterid': 8,
'dstaddrmode': 3, 'dstaddress': 00:12:4b:00:18:ed:25:0c, 'dstendpoint': 1}
zigpy_cc.uart DEBUG Send:
b"\xfe\x17%!\x8b\xbd<x'\xfe\xffW\x0b\x00\x01\x08\x00\x03\x0c%\xed\x18\x00K\x12\x00\x01\x95"
"""

data = b"\x02<x'\xfe\xffW\x0b\x00\x01\x08\x00\x03\x0c%\xed\x18\x00K\x12\x00\x01"

obj = ZpiObject.from_cluster(NWK(0x6292), 0, 0x0021, 0, 0, 2, data, 123)
obj = ZpiObject.from_cluster(NWK(0x6292), 0, 0x0021, 0, 0, 2, data)

assert (
"SREQ ZDO bindReq tsn: 2 {"
"'dstaddr': 0x6292, "
"'srcaddr': 00:0b:57:ff:fe:27:78:3c, "
"'srcendpoint': 1, "
"'clusterid': 8, "
"'dstaddrmode': 3, "
"'dstaddrmode': <AddressMode.ADDR_64BIT: 3>, "
"'dstaddress': 00:12:4b:00:18:ed:25:0c, "
"'dstendpoint': 1}" == str(obj)
)
Expand Down Expand Up @@ -431,7 +432,7 @@ def test_bind_req_serialize():
"srcaddr": EUI64(reversed(b"\x00\x0b\x57\xff\xfe\x27\x78\x3c")),
"srcendpoint": 1,
"clusterid": 8,
"dstaddrmode": 3,
"dstaddrmode": t.AddressMode.ADDR_64BIT,
"dstaddress": EUI64(reversed(b"\x00\x12\x4b\x00\x18\xed\x25\x0c")),
"dstendpoint": 1,
}
Expand All @@ -442,7 +443,7 @@ def test_bind_req_serialize():
"'srcaddr': 00:0b:57:ff:fe:27:78:3c, "
"'srcendpoint': 1, "
"'clusterid': 8, "
"'dstaddrmode': 3, "
"'dstaddrmode': <AddressMode.ADDR_64BIT: 3>, "
"'dstaddress': 00:12:4b:00:18:ed:25:0c, "
"'dstendpoint': 1}" == str(obj)
)
Expand Down
2 changes: 1 addition & 1 deletion version.py
Expand Up @@ -10,5 +10,5 @@
for line in file:
line = re.sub(r"(MAJOR_VERSION =).*", "\\1 " + parts[0], line)
line = re.sub(r"(MINOR_VERSION =).*", "\\1 " + parts[1], line)
line = re.sub(r"(PATCH_VERSION =).*", "\\1 \"" + parts[2] + "\"", line)
line = re.sub(r"(PATCH_VERSION =).*", '\\1 "' + parts[2] + '"', line)
print(line, end="")

0 comments on commit 5625ea5

Please sign in to comment.