diff --git a/python_otbr_api/tlv_parser.py b/python_otbr_api/tlv_parser.py index 174e12e..9af85d6 100644 --- a/python_otbr_api/tlv_parser.py +++ b/python_otbr_api/tlv_parser.py @@ -36,6 +36,7 @@ class MeshcopTLVType(IntEnum): JOINER_IID = 19 JOINER_RLOC = 20 JOINER_ROUTER_KEK = 21 + DURATION = 23 PROVISIONING_URL = 32 VENDOR_NAME_TLV = 33 VENDOR_MODEL_TLV = 34 @@ -51,8 +52,8 @@ class MeshcopTLVType(IntEnum): PERIOD = 55 SCAN_DURATION = 56 ENERGY_LIST = 57 - # Seen in a dataset imported through iOS companion app - APPLE_TAG_UNKNOWN = 74 + THREAD_DOMAIN_NAME = 59 + WAKEUP_CHANNEL = 74 DISCOVERYREQUEST = 128 DISCOVERYRESPONSE = 129 JOINERADVERTISEMENT = 241 diff --git a/tests/test_tlv_parser.py b/tests/test_tlv_parser.py index 21abc4e..255002a 100644 --- a/tests/test_tlv_parser.py +++ b/tests/test_tlv_parser.py @@ -14,6 +14,64 @@ ) +# Shared dataset covering the newly added Meshcop TLV types. +NEW_MESHCOP_DATASET = { + MeshcopTLVType.DURATION: MeshcopTLVItem( + MeshcopTLVType.DURATION, bytes.fromhex("05") + ), + MeshcopTLVType.PROVISIONING_URL: MeshcopTLVItem( + MeshcopTLVType.PROVISIONING_URL, "test".encode() + ), + MeshcopTLVType.VENDOR_NAME_TLV: MeshcopTLVItem( + MeshcopTLVType.VENDOR_NAME_TLV, "ACME".encode() + ), + MeshcopTLVType.UDP_ENCAPSULATION_TLV: MeshcopTLVItem( + MeshcopTLVType.UDP_ENCAPSULATION_TLV, bytes.fromhex("beef") + ), + MeshcopTLVType.IPV6_ADDRESS_TLV: MeshcopTLVItem( + MeshcopTLVType.IPV6_ADDRESS_TLV, + bytes.fromhex("20010db8000000000000000000000001"), + ), + MeshcopTLVType.PENDINGTIMESTAMP: MeshcopTLVItem( + MeshcopTLVType.PENDINGTIMESTAMP, bytes.fromhex("0000000000010000") + ), + MeshcopTLVType.DELAYTIMER: MeshcopTLVItem( + MeshcopTLVType.DELAYTIMER, bytes.fromhex("00001388") + ), + MeshcopTLVType.COUNT: MeshcopTLVItem( + MeshcopTLVType.COUNT, bytes.fromhex("03") + ), + MeshcopTLVType.PERIOD: MeshcopTLVItem( + MeshcopTLVType.PERIOD, bytes.fromhex("0032") + ), + MeshcopTLVType.SCAN_DURATION: MeshcopTLVItem( + MeshcopTLVType.SCAN_DURATION, bytes.fromhex("04") + ), + MeshcopTLVType.ENERGY_LIST: MeshcopTLVItem( + MeshcopTLVType.ENERGY_LIST, bytes.fromhex("010203") + ), + MeshcopTLVType.THREAD_DOMAIN_NAME: MeshcopTLVItem( + MeshcopTLVType.THREAD_DOMAIN_NAME, "home".encode() + ), + MeshcopTLVType.DISCOVERYREQUEST: MeshcopTLVItem( + MeshcopTLVType.DISCOVERYREQUEST, bytes.fromhex("00") + ), + MeshcopTLVType.DISCOVERYRESPONSE: MeshcopTLVItem( + MeshcopTLVType.DISCOVERYRESPONSE, bytes.fromhex("01") + ), + MeshcopTLVType.JOINERADVERTISEMENT: MeshcopTLVItem( + MeshcopTLVType.JOINERADVERTISEMENT, bytes.fromhex("02") + ), +} + +# Expected TLV hex for NEW_MESHCOP_DATASET; order follows the dict insertion order. +NEW_MESHCOP_DATASET_HEX = ( + "170105200474657374210441434d453002beef311020010db8000000000000000000000001" + "330800000000000100003404000013883601033702003238010439030102033b04686f6d65" + "800100810101f10102" +) + + def test_encode_tlv() -> None: """Test the TLV parser.""" dataset = { @@ -58,6 +116,9 @@ def test_encode_tlv() -> None: ).lower() ) + encoded_new_types = encode_tlv(NEW_MESHCOP_DATASET) + assert encoded_new_types == NEW_MESHCOP_DATASET_HEX + def test_parse_tlv() -> None: """Test the TLV parser.""" @@ -100,8 +161,11 @@ def test_parse_tlv() -> None: ), } + parsed_new_types = parse_tlv(NEW_MESHCOP_DATASET_HEX) + assert parsed_new_types == NEW_MESHCOP_DATASET + -def test_parse_tlv_apple() -> None: +def test_parse_tlv_with_wakeup_channel() -> None: """Test the TLV parser from a (truncated) dataset from an Apple BR.""" dataset_tlv = ( "0e08000065901a07000000030000194a0300000f35060004001fffc003104d79486f6d65313233" @@ -115,8 +179,8 @@ def test_parse_tlv_apple() -> None: MeshcopTLVType.CHANNEL: Channel( MeshcopTLVType.CHANNEL, bytes.fromhex("000019") ), - MeshcopTLVType.APPLE_TAG_UNKNOWN: MeshcopTLVItem( - MeshcopTLVType.APPLE_TAG_UNKNOWN, bytes.fromhex("00000f") + MeshcopTLVType.WAKEUP_CHANNEL : MeshcopTLVItem( + MeshcopTLVType.WAKEUP_CHANNEL , bytes.fromhex("00000f") ), MeshcopTLVType.CHANNELMASK: MeshcopTLVItem( MeshcopTLVType.CHANNELMASK, bytes.fromhex("0004001fffc0")