Skip to content

Commit

Permalink
Spec parsing: Add global commands for thermostat (project-chip#35607)
Browse files Browse the repository at this point in the history
* Spec parsing: Add global commands for thermostat

* use in-progress for clusters too

* Fix command check (merge conflict?)

* Restyled by isort

* Fix test that checks the default cluster dir

---------

Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
2 people authored and austina-csa committed Sep 20, 2024
1 parent 99f4a80 commit 7b716ef
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
5 changes: 1 addition & 4 deletions src/python_testing/TC_DeviceConformance.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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)
Expand Down
29 changes: 28 additions & 1 deletion src/python_testing/TestSpecParsingSupport.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down Expand Up @@ -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()
22 changes: 21 additions & 1 deletion src/python_testing/spec_parsing_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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] = {}
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 7b716ef

Please sign in to comment.