From f56678833ec997dfc6548b788c447a9219d4ed77 Mon Sep 17 00:00:00 2001 From: Scott Garrett Date: Tue, 1 Sep 2026 17:40:24 -0400 Subject: [PATCH] Updated to be pure bash and remove references to the web pages. --- .gitignore | 1 + CLAUDE.md | 255 ++- README.md | 75 +- __pycache__/gen-manufacturers.cpython-314.pyc | Bin 7710 -> 0 bytes gen-manufacturers.py | 17 +- matter-decode.sh | 6 +- matter-qr-decoder.html | 1498 ----------------- 7 files changed, 133 insertions(+), 1719 deletions(-) delete mode 100644 __pycache__/gen-manufacturers.cpython-314.pyc delete mode 100644 matter-qr-decoder.html diff --git a/.gitignore b/.gitignore index e43b0f9..6a4dae1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_Store +__pycache__ diff --git a/CLAUDE.md b/CLAUDE.md index 28498cc..17ff9fb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,136 +7,121 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co A collection of Matter commissioning QR decoders (the `MT:` URI format used by Matter/CHIP devices), plus a standalone bash decoder for Apple **HomeKit** setup codes (the `X-HM://` payload — a different on-wire format, in -`homekit-decode.sh`). For Matter, users either paste an `MT:` URI or scan a QR -code; the result shows the decoded payload (version, vendor/product IDs, -commissioning flow, discovery capabilities, discriminator, passcode). Key files: +`homekit-decode.sh`). For Matter, a user runs `matter-decode.sh` with an `MT:` +URI (as a positional argument or on stdin); it decodes the 84-bit payload and +prints the fields — version, vendor/product IDs, commissioning flow, discovery +capabilities, discriminator, passcode, and the derived manual pairing code. Key +files: -- `matter-qr-decoder.html` — the single-file browser app (Vue 3 + Bootstrap). -- `matter-decode.sh` — a pure-bash CLI port of the same decode logic (no camera - scanning; takes a URI as an argument or on stdin). +- `matter-decode.sh` — the pure-bash CLI Matter decoder. Takes an `MT:` URI as an + argument or on stdin and prints the decoded fields. It has no camera/QR-scanning + (that was the only feature the former browser app added, and it is gone). - `homekit-decode.sh` — a standalone pure-bash decoder for Apple **HomeKit** setup codes (the `X-HM://` payload an accessory shows on first setup — a - *different* format from Matter's `MT:`). No browser counterpart and no - companion TSV (the accessory-category table is inlined). See the - HomeKit setup-code decode section below. -- `manufacturers.tsv` — `vendor ID → name` table (~900 rows), shared by both - tools and optional (a missing file only drops the vendor-name lookup). + *different* format from Matter's `MT:`). No companion TSV (the accessory-category + table is inlined). See the HomeKit setup-code decode section below. +- `manufacturers.tsv` — `vendor ID → name` table (~900 rows), consumed by + `matter-decode.sh`; optional (a missing file only drops the vendor-name lookup). - `gen-manufacturers.py` — Python 3 stdlib script that regenerates `manufacturers.tsv`. Default source is the upstream `manufacturers.xml` **fetched over the network** (via `curl`; a GitHub `blob/` URL is auto-rewritten to its `raw.githubusercontent.com` form). A positional arg overrides with - another URL or a local XML file; passing `matter-qr-decoder.html` uses the - embedded `` block as an offline fallback. Reproduces the committed TSV - byte-for-byte. + another URL or a local XML file. Reproduces the committed TSV byte-for-byte. - `products.tsv` — 3-column `vendor ID → product ID → name` table, consumed by - `matter-decode.sh`'s `get_product_name()`: when the decoded vendor ID (or an + `matter-decode.sh`'s `get_product_name()`: when the decoded vendor ID (or an equivalent, see `vendor-equivalents.tsv`) is present, the product ID is resolved to a name and printed on the Product ID line. LIFX's rows are keyed - under `4870`. Optional — a missing file only drops the product-name lookup. + under `4870`. Optional — a missing file only drops the product-name lookup. - `vendor-equivalents.tsv` — 2-column `alias vendor ID → canonical vendor ID` - table, hand-edited, recording companies that are the same after a + table, hand-edited, recording companies that are the same after a merger/acquisition (e.g. Feit `5155` → LIFX `4870`). Used by - `matter-decode.sh` so a product resolves under either ID and the vendor name + `matter-decode.sh` so a product resolves under either ID and the vendor name is annotated `(a.k.a. ...)`. `#`-comment lines are ignored. Optional. - `gen-lifx-products.py` — Python 3 stdlib script that regenerates LIFX's rows - (vendor `4870`) in `products.tsv`. Default source is LIFX's upstream - `products.json` **fetched over the network** (via `curl`, falling back to - `urllib`); a positional arg overrides with another URL or a local `.json` - file. It **merges** LIFX's rows into `products.tsv` (dropping LIFX's old - rows, preserving every other vendor's), so re-running it is safe alongside - other vendors' generators. Caveat: `products.json` carries only a `pid` per - product (no separate Matter/CHIP product-id field), so the lookup assumes - LIFX's Matter product ID equals their `pid`. + (vendor `4870`) in `products.tsv`. Default source is LIFX's upstream + `products.json` **fetched over the network** (via `curl`, falling back to + `urllib`); a positional arg overrides with another URL or a local `.json` + file. It **merges** LIFX's rows into `products.tsv` (dropping LIFX's old + rows, preserving every other vendor's), so re-running it is safe alongside + other vendors' generators. Caveat: `products.json` carries only a `pid` per + product (no separate Matter/CHIP product-id field), so the lookup assumes + LIFX's Matter product ID equals their `pid`. - `README.md` — user-facing docs; this file documents the internals. ## Commands -There is **no build, test, lint, or package step** — this is not a git repo and has no -`package.json`. The entire app is one HTML file that runs in the browser: +There is **no build, test, lint, or package step** — this is not a build project. +The two decoders are standalone bash scripts and the two `gen-*.py` are Python 3 +stdlib regenerators; nothing is compiled or bundled. -- Run/develop: open `matter-qr-decoder.html` in a modern browser and edit it directly. -- Camera scanning (`getUserMedia`) requires a **secure context** — serve over HTTPS or - `localhost` (e.g. `python3 -m http.server` then open `http://localhost:8000`). -- The "Scan QR" feature uses the `BarcodeDetector` API, which is **Chromium-only** - (Chrome/Edge). Firefox/Safari fall back to a "not supported" message; paste-input works everywhere. -- The page loads Vue 3, Bootstrap 5.3, and Bootstrap Icons from CDNs, so it needs network access. +- Run the Matter decoder: `./matter-decode.sh "MT:..."`, or pipe it: + `echo "MT:..." | ./matter-decode.sh`. +- Run the HomeKit decoder: `./homekit-decode.sh [code]` (with no argument it + decodes the demo payload `005KEOUCE`). +- Regenerate `manufacturers.tsv`: `python3 gen-manufacturers.py` pulls the + pinned upstream `manufacturers.xml` over the network; pass a URL or a local + `.xml` file to use a different source. +- Regenerate LIFX's `products.tsv` rows: `python3 gen-lifx-products.py` (network + by default; a positional URL or local `.json` overrides). +- The decoders read their companion TSVs (`manufacturers.tsv`, `products.tsv`, + `vendor-equivalents.tsv`) from their own directory; a missing TSV drops that + extra lookup — it is never an error. +- Pure bash (3.x+); the `gen-*.py` scripts need only the Python 3 standard + library. ## Architecture -Everything lives in `matter-qr-decoder.html` (~1500 lines). Two regions matter: +The decode logic lives directly in the bash scripts — there is no shared library, +no embedded data map, and no build output. There are two decoders, and they +decode **two different on-wire formats**, so they are independent and should not +be unified. -1. **App logic** (the `', - html, re.DOTALL | re.IGNORECASE) - if not m: - sys.exit('error: no - - - -
-
-
-
- ← Tools -

Matter QR Code Decoder

-
-
- -
-
-
-
-
Input
-
-
-
- -
- - -
-
Enter a Matter QR code URI starting with "MT:" or scan a QR code
-
- -
- - -
-
-
-
Camera Preview
- -
-
- - -
-
-
- -
- {{ scanError }} -
- -
- {{ errorMessage }} -
-
-
- -
-
-
-
Decoded Payload
-
-
-
- - Enter a Matter QR code URI to see decoded information. -
- -
-
-
- - - - - - - - - - - - - - - - - - - -
Version:{{ decodedData.version }}
Vendor ID: - {{ formatVendorId(decodedData.vendorId) }} -
- {{ vendorName }} -
-
Product ID:{{ formatProductId(decodedData.productId) }}
Custom Flow:{{ getCustomFlowName(decodedData.customFlow) }}
-
-
- - - - - - - - - - - - - - - -
Discovery:{{ getDiscoveryCapabilities(decodedData.discoveryCapabilities) }}
Discriminator:{{ decodedData.discriminator }}
Passcode:{{ decodedData.passcode }}
-
-
-
-
-
- -
-
-
Data Encoding Format
-
-
-
-

Matter QR Format: MT:<base38-encoded-data>

- -

Bit Field Layout (84 bits total):

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldBitsPositionDescription
Version30-2QR format version (0-7)
Vendor ID163-18CSA-assigned vendor identifier
Product ID1619-34Vendor-assigned product identifier
Custom Flow235-36Commissioning flow type (0-3)
Discovery Caps837-44Supported discovery methods
Discriminator1245-56Device discriminator (0-4095)
Passcode2757-83Setup passcode (1-99999998)
- -

Base38 Encoding: Uses character set 0-9A-Z-. (38 chars total)

-
    -
  • 5 base38 chars → 3 bytes (most efficient)
  • -
  • 4 base38 chars → 2 bytes
  • -
  • 2 base38 chars → 1 byte
  • -
- -

Discovery Capabilities Bits:

-
    -
  • Bit 0: SoftAP support
  • -
  • Bit 1: BLE support
  • -
  • Bit 2: On IP Network support
  • -
-
-
-
-
-
-
-
- -
-
-
- Blog - Tools -
- © 2025 Tommie Gannert. All rights reserved. -
-
-
- - - - -