Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spec parsing: Add global commands for thermostat #35607

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading