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

Update PICS Generator to 1.4 #35619

Merged
Merged
Show file tree
Hide file tree
Changes from 3 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
44 changes: 8 additions & 36 deletions src/tools/PICS-generator/PICSGenerator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2023 Project CHIP Authors
# Copyright (c) 2024 Project CHIP Authors
ReneJosefsen marked this conversation as resolved.
Show resolved Hide resolved
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -24,6 +24,8 @@
import chip.clusters as Clusters
from rich.console import Console

from pics_generator_support import pics_xml_file_list_loader, map_cluster_name_to_pics_xml

# Add the path to python_testing folder, in order to be able to import from matter_testing_support
sys.path.append(os.path.abspath(sys.path[0] + "/../../python_testing"))
from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main # noqa: E402
Expand All @@ -40,49 +42,19 @@ def GenerateDevicePicsXmlFiles(clusterName, clusterPicsCode, featurePicsList, at

console.print(f"Handling PICS for {clusterName}")

# Map clusters to common XML template if needed
if "ICDManagement" == clusterName:
clusterName = "ICD Management"

elif "OTA Software Update Provider" in clusterName or "OTA Software Update Requestor" in clusterName:
clusterName = "OTA Software Update"

elif "On/Off" == clusterName:
clusterName = clusterName.replace("/", "-")

elif "GroupKeyManagement" == clusterName:
clusterName = "Group Communication"

elif "Wake On LAN" == clusterName or "Low Power" == clusterName:
clusterName = "Media Cluster"

elif "Operational Credentials" == clusterName:
clusterName = "Node Operational Credentials"

elif "Laundry Washer Controls" == clusterName:
clusterName = "Washer Controls"

# Workaround for naming colisions with current logic
elif "Thermostat" == clusterName:
clusterName = "Thermostat Cluster"

elif "Boolean State" == clusterName:
clusterName = "Boolean State Cluster"

if "AccessControl" in clusterName:
clusterName = "Access Control cluster"
picsFileName = map_cluster_name_to_pics_xml(clusterName, xmlFileList)

# Determine if file has already been handled and use this file
for outputFolderFileName in os.listdir(outputPathStr):
if clusterName in outputFolderFileName:
if picsFileName in outputFolderFileName:
xmlPath = outputPathStr
fileName = outputFolderFileName
break

# If no file is found in output folder, determine if there is a match for the cluster name in input folder
if fileName == "":
for file in xmlFileList:
if file.lower().startswith(clusterName.lower()):
if file.lower().startswith(picsFileName.lower()):
fileName = file
break
else:
Expand Down Expand Up @@ -420,10 +392,10 @@ def cleanDirectory(pathToClean):

# Load PICS XML templates
print("Capture list of PICS XML templates")
xmlFileList = os.listdir(xmlTemplatePathStr)
xmlFileList = pics_xml_file_list_loader(xmlTemplatePathStr, True)

# Setup output path
print(outputPathStr)
print(f"Output path: {outputPathStr}")

outputPath = pathlib.Path(outputPathStr)
if not outputPath.exists():
Expand Down
21 changes: 21 additions & 0 deletions src/tools/PICS-generator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ commissioning information:
python3 PICSGenerator.py --pics-template <pathToPicsTemplateFolder> --pics-output <outputPath> --commissioning-method ble-thread --discriminator <DESCRIMINATOR> --passcode <PASSCODE> --thread-dataset-hex <DATASET_AS_HEX>
```

or in case the device is e.g. an example running on a Linux/macOS system, use the on-network commissioning:

```
python3 PICSGenerator.py --pics-template <pathToPicsTemplateFolder> --pics-output <outputPath> --commissioning-method on-network --discriminator <DESCRIMINATOR> --passcode <PASSCODE>
```

In case the device uses a development PAA, the following parameter should be
added.

Expand All @@ -78,3 +84,18 @@ If a device has already been commissioned, the tool can be executed like this:
```
python3 PICSGenerator.py --pics-template <pathToPicsTemplateFolder> --pics-output <outputPath>
```

# Updates for future releases

Given each new release adds PICS files, to ensure the tool is able to map the cluster names to the PICS XML files,
the XMLPICSValidator script can be used to validate the mapping and will inform in case a cluster can not
be mapped to a PICS XML file.

The purpose of this script is mainly to make the update of this tool to future versions of Matter easier
and is not intended as a script for generating the PICS.

To run the XMLPICSValidator, the following command can be used:

```
python3 XMLPICSValidator.py --pics-template <pathToPicsTemplateFolder>
```
47 changes: 47 additions & 0 deletions src/tools/PICS-generator/XMLPICSValidator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#
andy31415 marked this conversation as resolved.
Show resolved Hide resolved
# Copyright (c) 2024 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import argparse
import sys
import os
from pics_generator_support import pics_xml_file_list_loader, map_cluster_name_to_pics_xml

# Add the path to python_testing folder, in order to be able to import from matter_testing_support
sys.path.append(os.path.abspath(sys.path[0] + "/../../python_testing"))
from spec_parsing_support import build_xml_clusters # noqa: E402


parser = argparse.ArgumentParser()
parser.add_argument('--pics-template', required=True)
args, unknown = parser.parse_known_args()

xml_template_path_str = args.pics_template

print("Build list of PICS XML")
pics_xml_file_list = pics_xml_file_list_loader(xml_template_path_str, True)

print("Build list of spec XML")
xml_clusters, problems = build_xml_clusters()

for cluster in xml_clusters:
pics_xml_file_name = map_cluster_name_to_pics_xml(xml_clusters[cluster].name, pics_xml_file_list)

if pics_xml_file_name:
print(f"{xml_clusters[cluster].name} - {pics_xml_file_name} ✅")
else:
print(
f"Could not find matching PICS XML file for {xml_clusters[cluster].name} - {xml_clusters[cluster].pics} (Provisional: {xml_clusters[cluster].is_provisional}) ❌")
77 changes: 77 additions & 0 deletions src/tools/PICS-generator/pics_generator_support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#
# Copyright (c) 2024 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import os

cluster_to_pics_dict = {
# Name mapping due to inconsistent naming of PICS files
"ICDManagement": "ICD Management",
"OTA Software Update Provider": "OTA Software Update",
"OTA Software Update Requestor": "OTA Software Update",
"On/Off": "On-Off",
"GroupKeyManagement": "Group Communication",
"Wake on LAN": "Media Cluster",
"Low Power": "Media Cluster",
"Keypad Input": "Media Cluster",
"Audio Output": "Media Cluster",
"Media Input": "Media Cluster",
"Target Navigator": "Media Cluster",
"Content Control": "Media Cluster",
"Channel": "Media Cluster",
"Media Playback": "Media Cluster",
"Account Login": "Media Cluster",
"Application Basic": "Media Cluster",
"Content Launcher": "Media Cluster",
"Content App Observer": "Media Cluster",
"Application Launch": "Media Cluster",
"Operational Credentials": "Node Operational Credentials",

# Workaround for naming colisions with current logic
"Thermostat": "Thermostat Cluster",
"Boolean State": "Boolean State Cluster",
"AccessControl": "Access Control Cluster",
}


def pics_xml_file_list_loader(pics_xml_path: str, log_loaded_pics_files: bool) -> list:

pics_xml_file_list = os.listdir(pics_xml_path)

if log_loaded_pics_files:
if not pics_xml_path.endswith('/'):
pics_xml_path += '/'

for pics_xml_file in pics_xml_file_list:
print(f"{pics_xml_path}/{pics_xml_file}")

return pics_xml_file_list


def map_cluster_name_to_pics_xml(cluster_name, pics_xml_file_list) -> str:
file_name = ""

try:
pics_file_name = cluster_to_pics_dict[cluster_name]
except KeyError:
pics_file_name = cluster_name
ReneJosefsen marked this conversation as resolved.
Show resolved Hide resolved

for file in pics_xml_file_list:
if file.lower().startswith(pics_file_name.lower()):
file_name = file
break

return file_name
Loading