Skip to content

Commit 42f868a

Browse files
ReneJosefsencecilleandy31415restyled-commits
authored
Update PICS Generator to 1.4 (#35619)
* 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 <cecille@google.com> Co-authored-by: Andrei Litvin <andy314@gmail.com> * Add XMLPICSValidator to wordlist * Restyled by prettier-markdown * Restyled by isort --------- Co-authored-by: C Freeman <cecille@google.com> Co-authored-by: Andrei Litvin <andy314@gmail.com> Co-authored-by: Restyled.io <commits@restyled.io>
1 parent 24919ed commit 42f868a

File tree

5 files changed

+153
-36
lines changed

5 files changed

+153
-36
lines changed

.github/.wordlist.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,7 @@ xFFF
16031603
xFFFF
16041604
xfffff
16051605
xFFFFFFEFFFFFFFFF
1606+
XMLPICSValidator
16061607
xtensa
16071608
xvzf
16081609
xwayland

src/tools/PICS-generator/PICSGenerator.py

+7-36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2023 Project CHIP Authors
2+
# Copyright (c) 2023-2024 Project CHIP Authors
33
# All rights reserved.
44
#
55
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,6 +22,7 @@
2222
import xml.etree.ElementTree as ET
2323

2424
import chip.clusters as Clusters
25+
from pics_generator_support import map_cluster_name_to_pics_xml, pics_xml_file_list_loader
2526
from rich.console import Console
2627

2728
# Add the path to python_testing folder, in order to be able to import from matter_testing_support
@@ -40,49 +41,19 @@ def GenerateDevicePicsXmlFiles(clusterName, clusterPicsCode, featurePicsList, at
4041

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

43-
# Map clusters to common XML template if needed
44-
if "ICDManagement" == clusterName:
45-
clusterName = "ICD Management"
46-
47-
elif "OTA Software Update Provider" in clusterName or "OTA Software Update Requestor" in clusterName:
48-
clusterName = "OTA Software Update"
49-
50-
elif "On/Off" == clusterName:
51-
clusterName = clusterName.replace("/", "-")
52-
53-
elif "GroupKeyManagement" == clusterName:
54-
clusterName = "Group Communication"
55-
56-
elif "Wake On LAN" == clusterName or "Low Power" == clusterName:
57-
clusterName = "Media Cluster"
58-
59-
elif "Operational Credentials" == clusterName:
60-
clusterName = "Node Operational Credentials"
61-
62-
elif "Laundry Washer Controls" == clusterName:
63-
clusterName = "Washer Controls"
64-
65-
# Workaround for naming colisions with current logic
66-
elif "Thermostat" == clusterName:
67-
clusterName = "Thermostat Cluster"
68-
69-
elif "Boolean State" == clusterName:
70-
clusterName = "Boolean State Cluster"
71-
72-
if "AccessControl" in clusterName:
73-
clusterName = "Access Control cluster"
44+
picsFileName = map_cluster_name_to_pics_xml(clusterName, xmlFileList)
7445

7546
# Determine if file has already been handled and use this file
7647
for outputFolderFileName in os.listdir(outputPathStr):
77-
if clusterName in outputFolderFileName:
48+
if picsFileName in outputFolderFileName:
7849
xmlPath = outputPathStr
7950
fileName = outputFolderFileName
8051
break
8152

8253
# If no file is found in output folder, determine if there is a match for the cluster name in input folder
8354
if fileName == "":
8455
for file in xmlFileList:
85-
if file.lower().startswith(clusterName.lower()):
56+
if file.lower().startswith(picsFileName.lower()):
8657
fileName = file
8758
break
8859
else:
@@ -420,10 +391,10 @@ def cleanDirectory(pathToClean):
420391

421392
# Load PICS XML templates
422393
print("Capture list of PICS XML templates")
423-
xmlFileList = os.listdir(xmlTemplatePathStr)
394+
xmlFileList = pics_xml_file_list_loader(xmlTemplatePathStr, True)
424395

425396
# Setup output path
426-
print(outputPathStr)
397+
print(f"Output path: {outputPathStr}")
427398

428399
outputPath = pathlib.Path(outputPathStr)
429400
if not outputPath.exists():

src/tools/PICS-generator/README.md

+24
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ commissioning information:
5959
python3 PICSGenerator.py --pics-template <pathToPicsTemplateFolder> --pics-output <outputPath> --commissioning-method ble-thread --discriminator <DESCRIMINATOR> --passcode <PASSCODE> --thread-dataset-hex <DATASET_AS_HEX>
6060
```
6161

62+
or in case the device is e.g. an example running on a Linux/macOS system, use
63+
the on-network commissioning:
64+
65+
```
66+
python3 PICSGenerator.py --pics-template <pathToPicsTemplateFolder> --pics-output <outputPath> --commissioning-method on-network --discriminator <DESCRIMINATOR> --passcode <PASSCODE>
67+
```
68+
6269
In case the device uses a development PAA, the following parameter should be
6370
added.
6471

@@ -78,3 +85,20 @@ If a device has already been commissioned, the tool can be executed like this:
7885
```
7986
python3 PICSGenerator.py --pics-template <pathToPicsTemplateFolder> --pics-output <outputPath>
8087
```
88+
89+
# Updates for future releases
90+
91+
Given each new release adds PICS files, to ensure the tool is able to map the
92+
cluster names to the PICS XML files, the XMLPICSValidator script can be used to
93+
validate the mapping and will inform in case a cluster can not be mapped to a
94+
PICS XML file.
95+
96+
The purpose of this script is mainly to make the update of this tool to future
97+
versions of Matter easier and is not intended as a script for generating the
98+
PICS.
99+
100+
To run the XMLPICSValidator, the following command can be used:
101+
102+
```
103+
python3 XMLPICSValidator.py --pics-template <pathToPicsTemplateFolder>
104+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#
2+
# Copyright (c) 2024 Project CHIP Authors
3+
# All rights reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
import argparse
19+
import os
20+
import sys
21+
22+
from pics_generator_support import map_cluster_name_to_pics_xml, pics_xml_file_list_loader
23+
24+
# Add the path to python_testing folder, in order to be able to import from matter_testing_support
25+
sys.path.append(os.path.abspath(sys.path[0] + "/../../python_testing"))
26+
from spec_parsing_support import build_xml_clusters # noqa: E402
27+
28+
parser = argparse.ArgumentParser()
29+
parser.add_argument('--pics-template', required=True)
30+
args, unknown = parser.parse_known_args()
31+
32+
xml_template_path_str = args.pics_template
33+
34+
print("Build list of PICS XML")
35+
pics_xml_file_list = pics_xml_file_list_loader(xml_template_path_str, True)
36+
37+
print("Build list of spec XML")
38+
xml_clusters, problems = build_xml_clusters()
39+
40+
for cluster in xml_clusters:
41+
pics_xml_file_name = map_cluster_name_to_pics_xml(xml_clusters[cluster].name, pics_xml_file_list)
42+
43+
if pics_xml_file_name:
44+
print(f"{xml_clusters[cluster].name} - {pics_xml_file_name} ✅")
45+
else:
46+
print(
47+
f"Could not find matching PICS XML file for {xml_clusters[cluster].name} - {xml_clusters[cluster].pics} (Provisional: {xml_clusters[cluster].is_provisional}) ❌")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#
2+
# Copyright (c) 2024 Project CHIP Authors
3+
# All rights reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
import os
19+
20+
cluster_to_pics_dict = {
21+
# Name mapping due to inconsistent naming of PICS files
22+
"ICDManagement": "ICD Management",
23+
"OTA Software Update Provider": "OTA Software Update",
24+
"OTA Software Update Requestor": "OTA Software Update",
25+
"On/Off": "On-Off",
26+
"GroupKeyManagement": "Group Communication",
27+
"Wake on LAN": "Media Cluster",
28+
"Low Power": "Media Cluster",
29+
"Keypad Input": "Media Cluster",
30+
"Audio Output": "Media Cluster",
31+
"Media Input": "Media Cluster",
32+
"Target Navigator": "Media Cluster",
33+
"Content Control": "Media Cluster",
34+
"Channel": "Media Cluster",
35+
"Media Playback": "Media Cluster",
36+
"Account Login": "Media Cluster",
37+
"Application Basic": "Media Cluster",
38+
"Content Launcher": "Media Cluster",
39+
"Content App Observer": "Media Cluster",
40+
"Application Launch": "Media Cluster",
41+
"Operational Credentials": "Node Operational Credentials",
42+
43+
# Workaround for naming colisions with current logic
44+
"Thermostat": "Thermostat Cluster",
45+
"Boolean State": "Boolean State Cluster",
46+
"AccessControl": "Access Control Cluster",
47+
}
48+
49+
50+
def pics_xml_file_list_loader(pics_xml_path: str, log_loaded_pics_files: bool) -> list:
51+
52+
pics_xml_file_list = os.listdir(pics_xml_path)
53+
54+
if log_loaded_pics_files:
55+
if not pics_xml_path.endswith('/'):
56+
pics_xml_path += '/'
57+
58+
for pics_xml_file in pics_xml_file_list:
59+
print(f"{pics_xml_path}/{pics_xml_file}")
60+
61+
return pics_xml_file_list
62+
63+
64+
def map_cluster_name_to_pics_xml(cluster_name, pics_xml_file_list) -> str:
65+
file_name = ""
66+
67+
pics_file_name = cluster_to_pics_dict.get(cluster_name, cluster_name)
68+
69+
for file in pics_xml_file_list:
70+
if file.lower().startswith(pics_file_name.lower()):
71+
file_name = file
72+
break
73+
74+
return file_name

0 commit comments

Comments
 (0)