diff --git a/src/python_testing/TC_DeviceConformance.py b/src/python_testing/TC_DeviceConformance.py index a6d6f19bfb53e7..86a981c86cde15 100644 --- a/src/python_testing/TC_DeviceConformance.py +++ b/src/python_testing/TC_DeviceConformance.py @@ -166,7 +166,6 @@ def record_warning(location, problem): if attribute_id not in self.xml_clusters[cluster_id].attributes.keys(): # TODO: Consolidate the range checks with IDM-10.1 once that lands if attribute_id <= 0x4FFF: - # manufacturer attribute record_error(location=location, problem='Standard attribute found on device, but not in spec') continue xml_attribute = self.xml_clusters[cluster_id].attributes[attribute_id] @@ -193,9 +192,7 @@ def check_spec_conformance_for_commands(command_type: CommandType): if command_id not in xml_commands_dict: # TODO: Consolidate range checks with IDM-10.1 once that lands if command_id <= 0xFF: - # manufacturer command - continue - record_error(location=location, problem='Standard command found on device, but not in spec') + record_error(location=location, problem='Standard command found on device, but not in spec') continue xml_command = xml_commands_dict[command_id] conformance_decision_with_choice = xml_command.conformance(feature_map, attribute_list, all_command_list) diff --git a/src/python_testing/TestSpecParsingSupport.py b/src/python_testing/TestSpecParsingSupport.py index aa2a68427607e4..c7f087cb03d834 100644 --- a/src/python_testing/TestSpecParsingSupport.py +++ b/src/python_testing/TestSpecParsingSupport.py @@ -272,7 +272,8 @@ def test_build_xml_override(self): asserts.assert_equal(set(in_progress.keys())-set(tot_xml_clusters.keys()), set(), "There are some in_progress clusters that are not included in the TOT spec") - str_path = str(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', 'data_model', 'master', 'clusters')) + str_path = str(os.path.join(os.path.dirname(os.path.realpath(__file__)), + '..', '..', 'data_model', 'in_progress', 'clusters')) string_override_check, problems = build_xml_clusters(str_path) asserts.assert_equal(string_override_check.keys(), self.spec_xml_clusters.keys(), "Mismatched cluster generation") @@ -462,6 +463,32 @@ def test_provisional_clusters(self): asserts.assert_in(id, clusters.keys(), "Non-provisional cluster not parsed") asserts.assert_false(clusters[id].is_provisional, "Non-provisional cluster marked as provisional") + def test_atomic_thermostat(self): + tot_xml_clusters, problems = build_xml_clusters(PrebuiltDataModelDirectory.kMaster) + one_three_clusters, problems = build_xml_clusters(PrebuiltDataModelDirectory.k1_3) + in_progress, problems = build_xml_clusters(PrebuiltDataModelDirectory.kInProgress) + + asserts.assert_in("Atomic Request", tot_xml_clusters[Clusters.Thermostat.id].command_map, + "Atomic request not found on thermostat command map") + request_id = tot_xml_clusters[Clusters.Thermostat.id].command_map["Atomic Request"] + asserts.assert_in(request_id, tot_xml_clusters[Clusters.Thermostat.id].accepted_commands.keys(), + "Atomic request not found in thermostat accepted command list") + + asserts.assert_in("Atomic Response", tot_xml_clusters[Clusters.Thermostat.id].command_map, + "Atomic response not found in the thermostat command map") + response_id = tot_xml_clusters[Clusters.Thermostat.id].command_map["Atomic Response"] + asserts.assert_in(response_id, tot_xml_clusters[Clusters.Thermostat.id].generated_commands.keys(), + "Atomic response not found in thermostat generated command list") + + asserts.assert_not_in( + "Atomic Request", one_three_clusters[Clusters.Thermostat.id].command_map, "Atomic request found on thermostat command map for 1.3") + asserts.assert_not_in(request_id, one_three_clusters[Clusters.Thermostat.id].accepted_commands.keys(), + "Atomic request found in thermostat accepted command list for 1.3") + asserts.assert_not_in( + "Atomic Response", one_three_clusters[Clusters.Thermostat.id].command_map, "Atomic response found on thermostat command map for 1.3") + asserts.assert_not_in(response_id, one_three_clusters[Clusters.Thermostat.id].generated_commands.keys(), + "Atomic request found in thermostat generated command list for 1.3") + if __name__ == "__main__": default_matter_test_main() diff --git a/src/python_testing/spec_parsing_support.py b/src/python_testing/spec_parsing_support.py index 445e168ecb4f5a..5a66a900c28c91 100644 --- a/src/python_testing/spec_parsing_support.py +++ b/src/python_testing/spec_parsing_support.py @@ -26,6 +26,7 @@ from typing import Callable, Optional import chip.clusters as Clusters +import conformance_support from chip.tlv import uint from conformance_support import (OPTIONAL_CONFORM, TOP_LEVEL_CONFORMANCE_TAGS, ConformanceDecision, ConformanceException, ConformanceParseParameters, feature, is_disallowed, mandatory, optional, or_operation, @@ -528,7 +529,7 @@ def _get_data_model_directory(data_model_directory: typing.Union[PrebuiltDataMod return data_model_directory -def build_xml_clusters(data_model_directory: typing.Union[PrebuiltDataModelDirectory, str] = PrebuiltDataModelDirectory.kMaster) -> tuple[dict[uint, XmlCluster], list[ProblemNotice]]: +def build_xml_clusters(data_model_directory: typing.Union[PrebuiltDataModelDirectory, str] = PrebuiltDataModelDirectory.kInProgress) -> tuple[dict[uint, XmlCluster], list[ProblemNotice]]: dir = _get_data_model_directory(data_model_directory, DataModelLevel.kCluster) clusters: dict[int, XmlCluster] = {} @@ -611,6 +612,25 @@ def remove_problem(location: typing.Union[CommandPathLocation, FeaturePathLocati 0x05: XmlAttribute(name='SupportedTemperatureLevels', datatype='list', conformance=feature(0x02, 'TL'), read_access=view, write_access=none, write_optional=False), } + # TODO: Need automated parsing for atomic attributes. + atomic_request_cmd_id = 0xFE + atomic_response_cmd_id = 0xFD + atomic_request_name = "Atomic Request" + atomic_response_name = "Atomic Response" + presets_name = "Presets" + schedules_name = "Schedules" + if clusters[Clusters.Thermostat.id].revision >= 8: + presents_id = clusters[Clusters.Thermostat.id].attribute_map[presets_name] + schedules_id = clusters[Clusters.Thermostat.id].attribute_map[schedules_name] + conformance = or_operation([conformance_support.attribute(presents_id, presets_name), + conformance_support.attribute(schedules_id, schedules_name)]) + clusters[Clusters.Thermostat.id].accepted_commands[atomic_request_cmd_id] = XmlCommand( + id=atomic_request_cmd_id, name=atomic_request_name, conformance=conformance) + clusters[Clusters.Thermostat.id].generated_commands[atomic_response_cmd_id] = XmlCommand( + id=atomic_response_cmd_id, name=atomic_response_name, conformance=conformance) + clusters[Clusters.Thermostat.id].command_map[atomic_request_name] = atomic_request_cmd_id + clusters[Clusters.Thermostat.id].command_map[atomic_response_name] = atomic_response_cmd_id + check_clusters_for_unknown_commands(clusters, problems) return clusters, problems