matter-clusters 0.4.0

Matter protocol cluster definitions (generated from the spec).
Documentation

matter-clusters

Typed Matter cluster definitions: per-cluster attribute/command/struct codecs, feature flags, enums (with Unknown(n) forward-compat) and bitmaps. The modules under gen/ are generated from a pinned @matter/model dump by the xtask codegen tool.

Part of matter-rust. Milestone 7.

What this crate does

  • Provides encode/decode functions for the attributes, commands, and structs of 47 Matter clusters (mandatory and optional attributes), as Matter TLV.
  • Models cluster enums with an Unknown(n) variant (forward-compatible decode), feature maps as bitflags, and nullable fields as Nullable<T> (distinct from Option<T>).
  • Generates all of the above from the spec model, gated against drift in CI.

What this crate does not do

  • It is not a full cluster set — only the 47 clusters below today. More arrive in later batches.
  • It does not provide generic or wildcard attribute access, or manufacturer-specific typed codecs. Reading arbitrary attributes a device publishes is the Interaction Model layer / high-level controller (see Reading attributes beyond these clusters).
  • It performs no IO and no session/transport work — it only encodes/decodes bytes.

Status

0.3.0. The 10 M7 clusters are generated and byte-parity tested against matter.js 0.16.11 (test-vectors/clusters/): BasicInformation, Descriptor, Identify, OnOff, LevelControl, ColorControl, OccupancySensing, TemperatureMeasurement, RelativeHumidityMeasurement, and DoorLock (Aliro features excluded). The M9-A2.1 pilot batch adds 5 read-only clusters — IlluminanceMeasurement, PressureMeasurement, FlowMeasurement, BooleanState, and Switch — decode-smoke tested (they reuse datatype shapes already byte-parity proven by the M7 set). The M9-A2.2 energy batch adds 4 more read-only clusters — PowerSource, ElectricalPowerMeasurement, ElectricalEnergyMeasurement, and AirQuality — decode-smoke tested, with a byte-parity vector for the new nested MeasurementAccuracyStruct (a struct holding a list-of-struct with optional fields). The M9-A2.3 actuator batch adds 5 read/write clusters — Thermostat, FanControl, ThermostatUserInterfaceConfiguration, PumpConfigurationAndControl, and WindowCovering — roundtrip (decode(encode(x)) == x) and decode-smoke tested, with a byte-parity vector for the list-typed AtomicRequest command. The M9-A2.4 utility batch adds 5 more clusters — Groups, Binding, GeneralDiagnostics, FixedLabel, and UserLabel — decode-smoke tested (incl. the Groups command encoders and the global FabricIndex typedef), with a byte-parity vector for the new struct-with-byte-fields shape (GeneralDiagnostics NetworkInterface: a hwadr bytes field, a keyword Type field, and byte-string-element lists). The M9-A2.5 management batch adds 4 more clusters — AccessControl, GroupKeyManagement, AdministratorCommissioning, and OtaSoftwareUpdateRequestor — codecs only (their protocol logic — ACL evaluation, group multicast, window-open orchestration, OTA — belongs to later milestones). Decode-smoke tested (incl. ACL entries whose subject-id subjects decode as u64), with a byte-parity vector for the recursive list-of-struct command encode (AccessControl.ReviewFabricRestrictions, whose Arl is a list of structs each carrying a nested list-of-struct). Those five batches took the library from 10 clusters to 33. Four more were added one at a time, each by the milestone that needed it: OperationalCredentials (M9-D2), OtaSoftwareUpdateProvider (M9-F1 — command-only, so it generates no attribute codecs), TimeSynchronization (M9-G-a), and IcdManagement (M9-G-c). That is 37. The concentration measurement family (Matter 1.2), reported missing by an external adopter in #112, adds the 10 read-only clusters that bring the total to the 47 generated today — CarbonMonoxide (0x040C), CarbonDioxide (0x040D), NitrogenDioxide (0x0413), Ozone (0x0415), Pm25 (0x042A), Formaldehyde (0x042B), Pm1 (0x042C), Pm10 (0x042D), TotalVolatileOrganicCompounds (0x042E), and Radon (0x042F) ConcentrationMeasurement. They derive from one base cluster and so share a single shape, which is why they are added as a family rather than piecemeal. That shape carries this crate's first float (single/FLOAT32) attributes, so alongside the per-cluster decode-smoke tests it gets a matter.js byte-parity vector, an explicit round-trip over the binary32 edges (signed zero, subnormals, infinities, NaN — compared by bits), and a proptest round-trip drawn uniformly from the whole binary32 bit space. A single attribute accepts a FLOAT32 element only, matching chip's strict TLVReader::Get(float&).

For any attribute not covered by these typed codecs — optional, manufacturer-specific, or a cluster not in this list — the generic Value path in matter-controller remains the universal answer. Hand-written support lives in types (Nullable<T>), error (ClusterError), and datatypes (SemanticTagStruct).

Usage

use matter_clusters::gen::{basic_information, on_off};

// Command payload — embed in an InvokeRequest.
let _toggle = on_off::encode_toggle();

// Attribute roundtrips: encode a value, decode it back.
let tlv = on_off::encode_on_time(30);
assert_eq!(on_off::decode_on_time(&tlv)?, 30);

let tlv = basic_information::encode_node_label(&"living room".to_string());
assert_eq!(basic_information::decode_node_label(&tlv)?, "living room");
# Ok::<(), matter_clusters::error::ClusterError>(())

See crates/matter-commissioning/examples/control_onoff.rs for an end-to-end read / toggle / write against a real device (runbook: docs/runbooks/m7.5-control-onoff.md).

Generated code

cargo xtask codegen writes src/gen/<cluster>.rs (+ globals.rs, mod.rs) from xtask/model/clusters.json. Do not edit the generated files by hand — change the emitter (xtask/src/codegen/) and regenerate. cargo xtask codegen --check gates drift in CI.

Reading attributes beyond these clusters

Typed codecs cover these clusters' mandatory and optional attributes. To read attributes of other clusters, or manufacturer-specific attributes, use the generic Interaction Model path: matter_interaction::parse_report_data yields (AttributePath, matter_codec::Value) for any attribute without a typed codec. A high-level generic + wildcard read API (and more typed clusters) arrive in later milestones.

Correctness posture

  • Byte-parity against matter.js 0.16.11 TLV combinators (test-vectors/clusters/): every generated codec round-trips to the captured oracle.
  • proptest roundtrips over attribute values.
  • A cargo-fuzz target over the generated decoders (weekly CI).
  • cargo xtask codegen --check fails CI if the committed src/gen/ drifts from what the emitter + clusters.json produce.

Cryptographic posture

matter-clusters performs no cryptography. It is pure data encoding.

MSRV

Rust 1.88 (workspace MSRV). See the workspace CHANGELOG.md.

License

Apache 2.0. See LICENSE at the workspace root.