diff --git a/src/python_testing/TC_ICDM_5_1.py b/src/python_testing/TC_ICDM_5_1.py index bfce8ca0fc86f0..60380473d02060 100644 --- a/src/python_testing/TC_ICDM_5_1.py +++ b/src/python_testing/TC_ICDM_5_1.py @@ -27,6 +27,7 @@ # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # === END CI TEST ARGUMENTS === +import asyncio import logging from dataclasses import dataclass @@ -36,11 +37,11 @@ from mdns_discovery import mdns_discovery from mobly import asserts -cluster = Clusters.Objects.IcdManagement -commands = cluster.Commands -attributes = cluster.Attributes -modes = cluster.Enums.OperatingModeEnum -ClientTypeEnum = cluster.Enums.ClientTypeEnum +Cluster = Clusters.Objects.IcdManagement +Commands = Cluster.Commands +Attributes = Cluster.Attributes +OperatingModeEnum = Cluster.Enums.OperatingModeEnum +ClientTypeEnum = Cluster.Enums.ClientTypeEnum @dataclass @@ -68,34 +69,22 @@ class TC_ICDM_5_1(MatterBaseTest): # Class Helper functions # - async def _read_icdm_attribute_expect_success(self, attribute): - return await self.read_single_attribute_check_success(endpoint=kRootEndpointId, cluster=cluster, attribute=attribute) + async def _read_icdm_attribute_expect_success(self, attribute) -> OperatingModeEnum: + return await self.read_single_attribute_check_success(endpoint=kRootEndpointId, cluster=Cluster, attribute=attribute) async def _send_single_icdm_command(self, command): return await self.send_single_cmd(command, endpoint=kRootEndpointId) - async def _get_icd_txt_record(self): + async def _get_icd_txt_record(self) -> OperatingModeEnum: discovery = mdns_discovery.MdnsDiscovery() - localCompressedNodeId = hex(self.default_controller.GetCompressedFabricId()) - dutNodeId = hex(self.dut_node_id) + service = await discovery.get_operational_service( + node_id=self.dut_node_id, + compressed_fabric_id=self.default_controller.GetCompressedFabricId(), + log_output=True, discovery_timeout_sec=240) - services = await discovery.get_all_services(log_output=True, discovery_timeout_sec=240) - icdTxtRecord = modes.kUnknownEnumValue.value - print("debugging mdns") - print(services) - asserts.assert_true(mdns_discovery.MdnsServiceType.OPERATIONAL.value in services, - "Could not find ICD operational service information.") - - for service in services[mdns_discovery.MdnsServiceType.OPERATIONAL.value]: - - # Generate hex for the compressedFabric and NodeId - serviceName = service.instance_name.split("-") - compressedFabric = hex(int(serviceName[0], 16)) - nodeId = hex(int(serviceName[1], 16)) - - # Find the correct MdnsServiceEntry - if localCompressedNodeId == compressedFabric and dutNodeId == nodeId: - icdTxtRecord = service.txt_record['ICD'] + icdTxtRecord = OperatingModeEnum(int(service.txt_record['ICD'])) + if icdTxtRecord.value != int(service.txt_record['ICD']): + raise AttributeError(f'Not a known ICD type: {service.txt_record["ICD"]}') return icdTxtRecord @@ -143,60 +132,62 @@ async def test_TC_ICDM_5_1(self): try: self.step(1) registeredClients = await self._read_icdm_attribute_expect_success( - attributes.RegisteredClients) + Attributes.RegisteredClients) for client in registeredClients: try: - await self._send_single_icdm_command(commands.UnregisterClient(checkInNodeID=client.checkInNodeID)) + await self._send_single_icdm_command(Commands.UnregisterClient(checkInNodeID=client.checkInNodeID)) except InteractionModelError as e: asserts.assert_equal( e.status, Status.Success, "Unexpected error returned") self.step("2a") - operatingMode = await self._read_icdm_attribute_expect_success(attributes.OperatingMode) - asserts.assert_equal(operatingMode, modes.kSit.value) + operatingMode = await self._read_icdm_attribute_expect_success(Attributes.OperatingMode) + asserts.assert_equal(operatingMode, OperatingModeEnum.kSit) self.step("2b") icdTxtRecord = await self._get_icd_txt_record() - asserts.assert_equal(int(icdTxtRecord), modes.kSit.value, "OperatingMode Is not in SIT mode.") + asserts.assert_equal(icdTxtRecord, OperatingModeEnum.kSit, "OperatingMode Is not in SIT mode.") self.step("3a") try: - await self._send_single_icdm_command(commands.RegisterClient(checkInNodeID=client1.checkInNodeID, monitoredSubject=client1.subjectId, key=client1.key, clientType=client1.clientType)) + await self._send_single_icdm_command(Commands.RegisterClient(checkInNodeID=client1.checkInNodeID, monitoredSubject=client1.subjectId, key=client1.key, clientType=client1.clientType)) except InteractionModelError as e: asserts.assert_equal( e.status, Status.Success, "Unexpected error returned") self.step("3b") - operatingMode = await self._read_icdm_attribute_expect_success(attributes.OperatingMode) - asserts.assert_equal(operatingMode, modes.kLit.value) + operatingMode = await self._read_icdm_attribute_expect_success(Attributes.OperatingMode) + asserts.assert_equal(operatingMode, OperatingModeEnum.kLit) + + # await asyncio.sleep(1) self.step("3c") icdTxtRecord = await self._get_icd_txt_record() - asserts.assert_equal(int(icdTxtRecord), modes.kLit.value, "OperatingMode Is not in Lit mode.") + asserts.assert_equal(icdTxtRecord, OperatingModeEnum.kLit, "OperatingMode Is not in Lit mode.") self.step(4) try: - await self._send_single_icdm_command(commands.UnregisterClient(checkInNodeID=client1.checkInNodeID)) + await self._send_single_icdm_command(Commands.UnregisterClient(checkInNodeID=client1.checkInNodeID)) except InteractionModelError as e: asserts.assert_equal( e.status, Status.Success, "Unexpected error returned") self.step("5a") - operatingMode = await self._read_icdm_attribute_expect_success(attributes.OperatingMode) - asserts.assert_equal(operatingMode, modes.kSit.value) + operatingMode = await self._read_icdm_attribute_expect_success(Attributes.OperatingMode) + asserts.assert_equal(operatingMode, OperatingModeEnum.kSit) self.step("5b") icdTxtRecord = await self._get_icd_txt_record() - asserts.assert_equal(int(icdTxtRecord), modes.kSit.value, "OperatingMode Is not in SIT mode.") + asserts.assert_equal(icdTxtRecord, OperatingModeEnum.kSit, "OperatingMode Is not in SIT mode.") finally: registeredClients = await self._read_icdm_attribute_expect_success( - attributes.RegisteredClients) + Attributes.RegisteredClients) for client in registeredClients: try: - await self._send_single_icdm_command(commands.UnregisterClient(checkInNodeID=client.checkInNodeID)) + await self._send_single_icdm_command(Commands.UnregisterClient(checkInNodeID=client.checkInNodeID)) except InteractionModelError as e: asserts.assert_equal( e.status, Status.Success, "Unexpected error returned") diff --git a/src/python_testing/mdns_discovery/mdns_discovery.py b/src/python_testing/mdns_discovery/mdns_discovery.py index 86661d65729da3..26ba8e08978406 100644 --- a/src/python_testing/mdns_discovery/mdns_discovery.py +++ b/src/python_testing/mdns_discovery/mdns_discovery.py @@ -99,6 +99,9 @@ def __init__(self): # A list of service types self._service_types = [] + # Filtering to apply for received data items + self._name_filter = None + # An asyncio Event to signal when a service has been discovered self._event = asyncio.Event() @@ -116,6 +119,7 @@ async def get_commissioner_service(self, log_output: bool = False, Returns: Optional[MdnsServiceInfo]: An instance of MdnsServiceInfo or None if timeout reached. """ + self._name_filter = None return await self._get_service(MdnsServiceType.COMMISSIONER, log_output, discovery_timeout_sec) async def get_commissionable_service(self, log_output: bool = False, @@ -131,10 +135,12 @@ async def get_commissionable_service(self, log_output: bool = False, Returns: Optional[MdnsServiceInfo]: An instance of MdnsServiceInfo or None if timeout reached. """ + self._name_filter = None return await self._get_service(MdnsServiceType.COMMISSIONABLE, log_output, discovery_timeout_sec) - async def get_operational_service(self, service_name: str = None, - service_type: str = None, + async def get_operational_service(self, + node_id: Optional[int] = None, + compressed_fabric_id: Optional[int] = None, discovery_timeout_sec: float = DISCOVERY_TIMEOUT_SEC, log_output: bool = False ) -> Optional[MdnsServiceInfo]: @@ -144,35 +150,16 @@ async def get_operational_service(self, service_name: str = None, Args: log_output (bool): Logs the discovered services to the console. Defaults to False. discovery_timeout_sec (float): Defaults to 15 seconds. - service_name (str): The unique name of the mDNS service. Defaults to None. - service_type (str): The service type of the service. Defaults to None. + node_id: the node id to create the service name from + compressed_fabric_id: the fabric id to create the service name from Returns: Optional[MdnsServiceInfo]: An instance of MdnsServiceInfo or None if timeout reached. """ # Validation to ensure both or none of the parameters are provided - if (service_name is None) != (service_type is None): - raise ValueError("Both service_name and service_type must be provided together or not at all.") - - mdns_service_info = None - - if service_name is None and service_type is None: - mdns_service_info = await self._get_service(MdnsServiceType.OPERATIONAL, log_output, discovery_timeout_sec) - else: - print(f"Looking for MDNS service type '{service_type}', service name '{service_name}'") - - # Get service info - service_info = AsyncServiceInfo(service_type, service_name) - is_discovered = await service_info.async_request(self._zc, 3000) - if is_discovered: - mdns_service_info = self._to_mdns_service_info_class(service_info) - self._discovered_services = {} - self._discovered_services[service_type] = [mdns_service_info] - if log_output: - self._log_output() - - return mdns_service_info + self._name_filter = f'{compressed_fabric_id:016x}-{node_id:016x}.{MdnsServiceType.OPERATIONAL.value}'.upper() + return await self._get_service(MdnsServiceType.OPERATIONAL, log_output, discovery_timeout_sec) async def get_border_router_service(self, log_output: bool = False, discovery_timeout_sec: float = DISCOVERY_TIMEOUT_SEC @@ -276,13 +263,18 @@ def _on_service_state_change( Returns: None: This method does not return any value. """ - if state_change.value == ServiceStateChange.Added.value: - self._event.set() - asyncio.ensure_future(self._query_service_info( - zeroconf, - service_type, - name) - ) + if state_change.value == ServiceStateChange.Removed.value: + return + + if self._name_filter is not None and name.upper() != self._name_filter: + return + + self._event.set() + asyncio.ensure_future(self._query_service_info( + zeroconf, + service_type, + name) + ) async def _query_service_info(self, zeroconf: Zeroconf, service_type: str, service_name: str) -> None: """