DM XMLs: Add function to dump cluster IDs for documentation (#32761)

* Add function to dump cluster IDs for documentation

* add json dump

* add Illuminance to word list

* remove unused var

* Change titles on docs to show zap vs. spec

* add the json for cluster_ids

* Restyled by whitespace

* Restyled by prettier-json

* Restyled by prettier-markdown

* Omit generated md files from restyler

---------

Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt
index 018ed26..f452704 100644
--- a/.github/.wordlist.txt
+++ b/.github/.wordlist.txt
@@ -668,6 +668,7 @@
 ifdefs
 IGMP
 ihex
+Illuminance
 IlluminanceMeasurement
 IM
 imager
diff --git a/.restyled.yaml b/.restyled.yaml
index be74f5b..5e9a492 100644
--- a/.restyled.yaml
+++ b/.restyled.yaml
@@ -86,7 +86,8 @@
     - "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 0000000..be7c946
--- /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 8447850..b7615a4 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -20,8 +20,10 @@
 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 0000000..0271542
--- /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 eb3dfde..eedfb71 100644
--- a/docs/clusters.md
+++ b/docs/zap_clusters.md
@@ -8,7 +8,7 @@
   - ./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 fc49931..3acb051 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 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 bc9f7c8..33473c0 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 @@
   - ./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 016f92d..b947b99 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 @@
     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_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_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_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 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()