Skip to content

Commit

Permalink
Update PICS Generator to 1.4 (project-chip#35619)
Browse files Browse the repository at this point in the history
* Updated PICS Generator to match 1.4 PICS

* Add script to validate PICS and cluster macthing

* Updated based on review feedback

* Apply suggestions from code review

Co-authored-by: C Freeman <[email protected]>
Co-authored-by: Andrei Litvin <[email protected]>

* Add XMLPICSValidator to wordlist

* Restyled by prettier-markdown

* Restyled by isort

---------

Co-authored-by: C Freeman <[email protected]>
Co-authored-by: Andrei Litvin <[email protected]>
Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
4 people authored and yyzhong-g committed Dec 11, 2024
1 parent 906abb1 commit 4ae3a7f
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 36 deletions.
1 change: 1 addition & 0 deletions .github/.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1603,6 +1603,7 @@ xFFF
xFFFF
xfffff
xFFFFFFEFFFFFFFFF
XMLPICSValidator
xtensa
xvzf
xwayland
Expand Down
43 changes: 7 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) 2023-2024 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -22,6 +22,7 @@
import xml.etree.ElementTree as ET

import chip.clusters as Clusters
from pics_generator_support import map_cluster_name_to_pics_xml, pics_xml_file_list_loader
from rich.console import Console

# Add the path to python_testing folder, in order to be able to import from matter_testing_support
Expand All @@ -40,49 +41,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 +391,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
24 changes: 24 additions & 0 deletions src/tools/PICS-generator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ 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 +85,20 @@ 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 @@
#
# 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 os
import sys

from pics_generator_support import map_cluster_name_to_pics_xml, pics_xml_file_list_loader

# 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}) ❌")
74 changes: 74 additions & 0 deletions src/tools/PICS-generator/pics_generator_support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#
# 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 = ""

pics_file_name = cluster_to_pics_dict.get(cluster_name, cluster_name)

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

return file_name

0 comments on commit 4ae3a7f

Please sign in to comment.