diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 018ed267925642..f45270454a88a5 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -668,6 +668,7 @@ ifdef ifdefs IGMP ihex +Illuminance IlluminanceMeasurement IM imager diff --git a/.restyled.yaml b/.restyled.yaml index be74f5b47aa61d..5e9a492aaaaf41 100644 --- a/.restyled.yaml +++ b/.restyled.yaml @@ -86,7 +86,8 @@ exclude: - "integrations/docker/build-all.sh" # tries to quote loop variable - "scripts/setup/pigweed.json" # TODO(#29547). This file is temporary copy from pigweed repo that has minor edits. No restyle help in diff. - "docs/ERROR_CODES.md" # generated by scripts, not easy to align tables - - "docs/clusters.md" # generated by scripts, not easy to align tables + - "docs/zap_clusters.md" # generated by scripts, not easy to align tables + - "docs/spec_clusters.md" # generated by scripts, not easy to align tables - "docs/testing/yaml_pseudocluster.md" # generated by scripts, restyler makes the tables render improperly - "docs/testing/yaml_schema.md" # generated by scripts, restyler makes the tables render improperly diff --git a/data_model/clusters/cluster_ids.json b/data_model/clusters/cluster_ids.json new file mode 100644 index 00000000000000..be7c9464690ea8 --- /dev/null +++ b/data_model/clusters/cluster_ids.json @@ -0,0 +1,115 @@ +{ + "3": "Identify", + "4": "Groups", + "6": "On/Off", + "8": "Level Control", + "28": "Pulse Width Modulation", + "29": "Descriptor", + "30": "Binding", + "31": "AccessControl", + "37": "Actions", + "40": "Basic Information", + "41": "OTA Software Update Provider", + "42": "OTA Software Update Requestor", + "43": "Localization Configuration", + "44": "Time Format Localization", + "45": "Unit Localization", + "46": "Power Source Configuration", + "47": "Power Source", + "48": "General Commissioning", + "49": "Network Commissioning", + "50": "Diagnostic Logs", + "51": "General Diagnostics", + "52": "Software Diagnostics", + "53": "Thread Network Diagnostics", + "54": "Wi", + "55": "Ethernet Network Diagnostics", + "56": "Time Synchronization", + "57": "Bridged Device Basic Information", + "59": "Switch", + "60": "Administrator Commissioning", + "62": "Operational Credentials", + "63": "GroupKeyManagement", + "64": "Fixed Label", + "65": "User Label", + "69": "Boolean State", + "70": "ICDManagement", + "72": "Oven Cavity Operational State", + "73": "Oven Mode", + "74": "Laundry Dryer Controls", + "80": "Mode Select", + "81": "Laundry Washer Mode", + "82": "Refrigerator And Temperature Controlled Cabinet Mode", + "83": "Laundry Washer Controls", + "84": "RVC Run Mode", + "85": "RVC Clean Mode", + "86": "Temperature Control", + "87": "Refrigerator Alarm", + "89": "Dishwasher Mode", + "91": "Air Quality", + "92": "Smoke CO Alarm", + "93": "Dishwasher Alarm", + "94": "Microwave Oven Mode", + "95": "Microwave Oven Control", + "96": "Operational State", + "97": "RVC Operational State", + "98": "Scenes Management", + "113": "HEPA Filter Monitoring", + "114": "Activated Carbon Filter Monitoring", + "128": "Boolean State Configuration", + "129": "Valve Configuration and Control", + "144": "Electrical Power Measurement", + "145": "Electrical Energy Measurement", + "148": "Water Heater Management", + "149": "Energy Price", + "150": "Demand Response and Load Control", + "151": "Messages", + "152": "Device Energy Management", + "153": "Energy EVSE", + "154": "Energy Calendar", + "155": "Energy Preference", + "156": "Power Topology", + "157": "Energy EVSE Mode", + "158": "Water Heater Mode", + "159": "Device Energy Management Mode", + "257": "Door Lock", + "258": "Window Covering", + "512": "Pump Configuration and Control", + "513": "Thermostat", + "514": "Fan Control", + "516": "Thermostat User Interface Configuration", + "768": "Color Control", + "769": "Ballast Configuration", + "1024": "Illuminance Measurement", + "1026": "Temperature Measurement", + "1027": "Pressure Measurement", + "1028": "Flow Measurement", + "1029": "Relative Humidity Measurement", + "1030": "Occupancy Sensing", + "1036": "Carbon Monoxide Concentration Measurement", + "1037": "Carbon Dioxide Concentration Measurement", + "1043": "Nitrogen Dioxide Concentration Measurement", + "1045": "Ozone Concentration Measurement", + "1066": "PM2", + "1067": "Formaldehyde Concentration Measurement", + "1068": "PM1 Concentration Measurement", + "1069": "PM10 Concentration Measurement", + "1070": "Total Volatile Organic Compounds Concentration Measurement", + "1071": "Radon Concentration Measurement", + "1104": "Network Identity Management", + "1105": "Wi", + "1283": "Wake on LAN", + "1284": "Channel", + "1285": "Target Navigator", + "1286": "Media Playback", + "1287": "Media Input", + "1288": "Low Power", + "1289": "Keypad Input", + "1290": "Content Launcher", + "1291": "Audio Output", + "1292": "Application Launcher", + "1293": "Application Basic", + "1294": "Account Login", + "1295": "Content Control", + "1296": "Content App Observer" +} diff --git a/docs/index.md b/docs/index.md index 8447850784787f..b7615a476818df 100644 --- a/docs/index.md +++ b/docs/index.md @@ -20,8 +20,10 @@ testing/index tools/index BUG_REPORT code_generation -clusters +zap_clusters +spec_clusters ERROR_CODES + ``` ```{include} README.md diff --git a/docs/spec_clusters.md b/docs/spec_clusters.md new file mode 100644 index 00000000000000..02715424bbb5d8 --- /dev/null +++ b/docs/spec_clusters.md @@ -0,0 +1,118 @@ +# List of currently defined spec clusters +This file was **AUTOMATICALLY** generated by `python scripts/generate_spec_xml.py`. DO NOT EDIT BY HAND! + +| ID (Decimal) | ID (hex) | Name | +|--------------|----------|----------------------------------------------------------| +|3 |0x0003 |Identify | +|4 |0x0004 |Groups | +|6 |0x0006 |On/Off | +|8 |0x0008 |Level Control | +|28 |0x001C |Pulse Width Modulation | +|29 |0x001D |Descriptor | +|30 |0x001E |Binding | +|31 |0x001F |AccessControl | +|37 |0x0025 |Actions | +|40 |0x0028 |Basic Information | +|41 |0x0029 |OTA Software Update Provider | +|42 |0x002A |OTA Software Update Requestor | +|43 |0x002B |Localization Configuration | +|44 |0x002C |Time Format Localization | +|45 |0x002D |Unit Localization | +|46 |0x002E |Power Source Configuration | +|47 |0x002F |Power Source | +|48 |0x0030 |General Commissioning | +|49 |0x0031 |Network Commissioning | +|50 |0x0032 |Diagnostic Logs | +|51 |0x0033 |General Diagnostics | +|52 |0x0034 |Software Diagnostics | +|53 |0x0035 |Thread Network Diagnostics | +|54 |0x0036 |Wi | +|55 |0x0037 |Ethernet Network Diagnostics | +|56 |0x0038 |Time Synchronization | +|57 |0x0039 |Bridged Device Basic Information | +|59 |0x003B |Switch | +|60 |0x003C |Administrator Commissioning | +|62 |0x003E |Operational Credentials | +|63 |0x003F |GroupKeyManagement | +|64 |0x0040 |Fixed Label | +|65 |0x0041 |User Label | +|69 |0x0045 |Boolean State | +|70 |0x0046 |ICDManagement | +|72 |0x0048 |Oven Cavity Operational State | +|73 |0x0049 |Oven Mode | +|74 |0x004A |Laundry Dryer Controls | +|80 |0x0050 |Mode Select | +|81 |0x0051 |Laundry Washer Mode | +|82 |0x0052 |Refrigerator And Temperature Controlled Cabinet Mode | +|83 |0x0053 |Laundry Washer Controls | +|84 |0x0054 |RVC Run Mode | +|85 |0x0055 |RVC Clean Mode | +|86 |0x0056 |Temperature Control | +|87 |0x0057 |Refrigerator Alarm | +|89 |0x0059 |Dishwasher Mode | +|91 |0x005B |Air Quality | +|92 |0x005C |Smoke CO Alarm | +|93 |0x005D |Dishwasher Alarm | +|94 |0x005E |Microwave Oven Mode | +|95 |0x005F |Microwave Oven Control | +|96 |0x0060 |Operational State | +|97 |0x0061 |RVC Operational State | +|98 |0x0062 |Scenes Management | +|113 |0x0071 |HEPA Filter Monitoring | +|114 |0x0072 |Activated Carbon Filter Monitoring | +|128 |0x0080 |Boolean State Configuration | +|129 |0x0081 |Valve Configuration and Control | +|144 |0x0090 |Electrical Power Measurement | +|145 |0x0091 |Electrical Energy Measurement | +|148 |0x0094 |Water Heater Management | +|149 |0x0095 |Energy Price | +|150 |0x0096 |Demand Response and Load Control | +|151 |0x0097 |Messages | +|152 |0x0098 |Device Energy Management | +|153 |0x0099 |Energy EVSE | +|154 |0x009A |Energy Calendar | +|155 |0x009B |Energy Preference | +|156 |0x009C |Power Topology | +|157 |0x009D |Energy EVSE Mode | +|158 |0x009E |Water Heater Mode | +|159 |0x009F |Device Energy Management Mode | +|257 |0x0101 |Door Lock | +|258 |0x0102 |Window Covering | +|512 |0x0200 |Pump Configuration and Control | +|513 |0x0201 |Thermostat | +|514 |0x0202 |Fan Control | +|516 |0x0204 |Thermostat User Interface Configuration | +|768 |0x0300 |Color Control | +|769 |0x0301 |Ballast Configuration | +|1024 |0x0400 |Illuminance Measurement | +|1026 |0x0402 |Temperature Measurement | +|1027 |0x0403 |Pressure Measurement | +|1028 |0x0404 |Flow Measurement | +|1029 |0x0405 |Relative Humidity Measurement | +|1030 |0x0406 |Occupancy Sensing | +|1036 |0x040C |Carbon Monoxide Concentration Measurement | +|1037 |0x040D |Carbon Dioxide Concentration Measurement | +|1043 |0x0413 |Nitrogen Dioxide Concentration Measurement | +|1045 |0x0415 |Ozone Concentration Measurement | +|1066 |0x042A |PM2 | +|1067 |0x042B |Formaldehyde Concentration Measurement | +|1068 |0x042C |PM1 Concentration Measurement | +|1069 |0x042D |PM10 Concentration Measurement | +|1070 |0x042E |Total Volatile Organic Compounds Concentration Measurement| +|1071 |0x042F |Radon Concentration Measurement | +|1104 |0x0450 |Network Identity Management | +|1105 |0x0451 |Wi | +|1283 |0x0503 |Wake on LAN | +|1284 |0x0504 |Channel | +|1285 |0x0505 |Target Navigator | +|1286 |0x0506 |Media Playback | +|1287 |0x0507 |Media Input | +|1288 |0x0508 |Low Power | +|1289 |0x0509 |Keypad Input | +|1290 |0x050A |Content Launcher | +|1291 |0x050B |Audio Output | +|1292 |0x050C |Application Launcher | +|1293 |0x050D |Application Basic | +|1294 |0x050E |Account Login | +|1295 |0x050F |Content Control | +|1296 |0x0510 |Content App Observer | diff --git a/docs/clusters.md b/docs/zap_clusters.md similarity index 99% rename from docs/clusters.md rename to docs/zap_clusters.md index eb3dfde53abb80..eedfb7190e2f27 100644 --- a/docs/clusters.md +++ b/docs/zap_clusters.md @@ -8,7 +8,7 @@ Generally regenerate using one of: - ./scripts/codegen.py --output-dir docs --generator summary-markdown src/controller/data_model/controller-clusters.matter --> -## List of currently defined clusters +## List of currently defined ZAP clusters | Code (dec) | Code (hex) | Name | | ---------- | ---------- | ------------------------------------------------------- | diff --git a/scripts/py_matter_idl/matter_idl/generators/markdown/__init__.py b/scripts/py_matter_idl/matter_idl/generators/markdown/__init__.py index fc49931ff60f21..3acb05110c463f 100644 --- a/scripts/py_matter_idl/matter_idl/generators/markdown/__init__.py +++ b/scripts/py_matter_idl/matter_idl/generators/markdown/__init__.py @@ -28,7 +28,7 @@ def __init__(self, storage: GeneratorStorage, idl: Idl, **kargs): def internal_render_all(self): self.internal_render_one_output( template_path="clusters_markdown.jinja", - output_file_name="clusters.md", + output_file_name="zap_clusters.md", vars={ 'idl': self.idl, } diff --git a/scripts/py_matter_idl/matter_idl/generators/markdown/clusters_markdown.jinja b/scripts/py_matter_idl/matter_idl/generators/markdown/clusters_markdown.jinja index bc9f7c8ad36a85..33473c028d83fb 100644 --- a/scripts/py_matter_idl/matter_idl/generators/markdown/clusters_markdown.jinja +++ b/scripts/py_matter_idl/matter_idl/generators/markdown/clusters_markdown.jinja @@ -8,7 +8,7 @@ Generally regenerate using one of: - ./scripts/codegen.py --output-dir docs --generator summary-markdown src/controller/data_model/controller-clusters.matter --> -## List of currently defined clusters +## List of currently defined ZAP clusters | Code (dec) | Code (hex) | Name | | ---------- | ---------- | ------------------------------------------------------- | diff --git a/scripts/spec_xml/generate_spec_xml.py b/scripts/spec_xml/generate_spec_xml.py index 016f92d4b5759a..b947b997665251 100755 --- a/scripts/spec_xml/generate_spec_xml.py +++ b/scripts/spec_xml/generate_spec_xml.py @@ -15,14 +15,20 @@ # limitations under the License. import glob +import json import os import re import subprocess +import sys import click -DEFAULT_CHIP_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) -DEFAULT_OUTPUT_DIR = os.path.abspath(os.path.join(DEFAULT_CHIP_ROOT, 'data_model')) +DEFAULT_CHIP_ROOT = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..')) +DEFAULT_OUTPUT_DIR = os.path.abspath( + os.path.join(DEFAULT_CHIP_ROOT, 'data_model')) +DEFAULT_DOCUMENTATION_FILE = os.path.abspath( + os.path.join(DEFAULT_CHIP_ROOT, 'docs', 'spec_clusters.md')) def get_xml_path(filename, output_dir): @@ -56,14 +62,17 @@ def main(scraper, spec_root, output_dir, dry_run): scrape_device_types(scraper, spec_root, output_dir, dry_run) if not dry_run: dump_versions(scraper, spec_root, output_dir) + dump_cluster_ids(output_dir) def scrape_clusters(scraper, spec_root, output_dir, dry_run): src_dir = os.path.abspath(os.path.join(spec_root, 'src')) - sdm_clusters_dir = os.path.abspath(os.path.join(src_dir, 'service_device_management')) + sdm_clusters_dir = os.path.abspath( + os.path.join(src_dir, 'service_device_management')) app_clusters_dir = os.path.abspath(os.path.join(src_dir, 'app_clusters')) dm_clusters_dir = os.path.abspath(os.path.join(src_dir, 'data_model')) - media_clusters_dir = os.path.abspath(os.path.join(app_clusters_dir, 'media')) + media_clusters_dir = os.path.abspath( + os.path.join(app_clusters_dir, 'media')) clusters_output_dir = os.path.abspath(os.path.join(output_dir, 'clusters')) dm_clusters_list = ['ACL-Cluster.adoc', 'Binding-Cluster.adoc', 'bridge-clusters.adoc', 'Descriptor-Cluster.adoc', 'Group-Key-Management-Cluster.adoc', 'ICDManagement.adoc', @@ -79,7 +88,8 @@ def scrape_clusters(scraper, spec_root, output_dir, dry_run): def scrape_cluster(filename: str) -> None: xml_path = get_xml_path(filename, clusters_output_dir) - cmd = [scraper, 'cluster', '-i', filename, '-o', xml_path, '-nd', '--define', 'in-progress'] + cmd = [scraper, 'cluster', '-i', filename, '-o', + xml_path, '-nd', '--define', 'in-progress'] if dry_run: print(cmd) else: @@ -100,8 +110,10 @@ def scrape_all_clusters(dir: str, exclude_list: list[str] = []) -> None: def scrape_device_types(scraper, spec_root, output_dir, dry_run): - device_type_dir = os.path.abspath(os.path.join(spec_root, 'src', 'device_types')) - device_types_output_dir = os.path.abspath(os.path.join(output_dir, 'device_types')) + device_type_dir = os.path.abspath( + os.path.join(spec_root, 'src', 'device_types')) + device_types_output_dir = os.path.abspath( + os.path.join(output_dir, 'device_types')) clusters_output_dir = os.path.abspath(os.path.join(output_dir, 'clusters')) if not os.path.exists(device_types_output_dir): @@ -109,7 +121,8 @@ def scrape_device_types(scraper, spec_root, output_dir, dry_run): def scrape_device_type(filename: str) -> None: xml_path = get_xml_path(filename, device_types_output_dir) - cmd = [scraper, 'devicetype', '-c', clusters_output_dir, '-nd', '-i', filename, '-o', xml_path] + cmd = [scraper, 'devicetype', '-c', clusters_output_dir, + '-nd', '-i', filename, '-o', xml_path] if dry_run: print(cmd) else: @@ -125,17 +138,57 @@ def scrape_device_type(filename: str) -> None: def dump_versions(scraper, spec_root, output_dir): sha_file = os.path.abspath(os.path.join(output_dir, 'spec_sha')) - out = subprocess.run(['git', 'rev-parse', 'HEAD'], capture_output=True, encoding="utf8", cwd=spec_root) + out = subprocess.run(['git', 'rev-parse', 'HEAD'], + capture_output=True, encoding="utf8", cwd=spec_root) sha = out.stdout with open(sha_file, 'wt', encoding='utf8') as output: output.write(sha) scraper_file = os.path.abspath(os.path.join(output_dir, 'scraper_version')) - out = subprocess.run([scraper, '--version'], capture_output=True, encoding="utf8") + out = subprocess.run([scraper, '--version'], + capture_output=True, encoding="utf8") version = out.stdout with open(scraper_file, "wt", encoding='utf8') as output: output.write(version) +def dump_cluster_ids(output_dir): + python_testing_path = os.path.abspath( + os.path.join(DEFAULT_CHIP_ROOT, 'src', 'python_testing')) + sys.path.insert(0, python_testing_path) + clusters_output_dir = os.path.abspath( + os.path.join(output_dir, 'clusters')) + + from spec_parsing_support import build_xml_clusters + + header = '# List of currently defined spec clusters\n' + header += 'This file was **AUTOMATICALLY** generated by `python scripts/generate_spec_xml.py`. DO NOT EDIT BY HAND!\n\n' + + clusters, problems = build_xml_clusters() + all_name_lens = [len(c.name) for c in clusters.values()] + name_len = max(all_name_lens) + title_id_decimal = ' ID (Decimal) ' + title_id_hex = ' ID (hex) ' + title_name_raw = ' Name ' + title_name = f'{title_name_raw:<{name_len}}' + dec_len = len(title_id_decimal) + hex_len = len(title_id_hex) + title = f'|{title_id_decimal}|{title_id_hex}|{title_name}|\n' + hashes = f'|{"-" * dec_len}|{"-" * hex_len}|{"-" * name_len}|\n' + s = title + hashes + json_dict = {id: c.name for id, c in sorted(clusters.items())} + for id, cluster in sorted(clusters.items()): + hex_id = f'0x{id:04X}' + s += f'|{id:<{dec_len}}|{hex_id:<{hex_len}}|{cluster.name:<{name_len}}|\n' + + with open(DEFAULT_DOCUMENTATION_FILE, 'w') as fout: + fout.write(header) + fout.write(s) + + json_file = os.path.join(clusters_output_dir, 'cluster_ids.json') + with open(json_file, "w") as outfile: + json.dump(json_dict, outfile, indent=2) + + if __name__ == '__main__': main()