matter_clusters/lib.rs
1//! Typed Matter cluster definitions — generated from the Matter spec.
2//!
3//! Per-cluster attribute / command / struct **codecs** (encode/decode to Matter
4//! TLV), feature bitflags, enums (with an `Unknown(n)` variant for
5//! forward-compatibility), and bitmaps. The cluster modules live under
6//! [`gen`]; the hand-written foundation is [`Nullable<T>`](types::Nullable)
7//! (distinct from `Option`), [`ClusterError`](error::ClusterError), and
8//! [`datatypes::SemanticTagStruct`].
9//!
10//! # Pipeline
11//!
12//! The `gen/` modules are generated, not hand-written: a pinned `@matter/model`
13//! dump becomes the committed `xtask/model/clusters.json`, which
14//! `cargo xtask codegen` turns into the committed `src/gen/*.rs`. CI gates drift
15//! with `cargo xtask codegen --check`. **Do not edit `src/gen/` by hand** —
16//! change the emitter in `xtask/src/codegen/` and regenerate.
17//!
18//! Correctness: the generated codecs are **byte-parity tested against matter.js
19//! 0.16.11** (`test-vectors/clusters/`), with `proptest` roundtrips and a
20//! `cargo-fuzz` target.
21//!
22//! # Clusters
23//!
24//! M7 (byte-parity tested): `BasicInformation`, `Descriptor`, `Identify`,
25//! `OnOff`, `LevelControl`, `ColorControl`, `OccupancySensing`,
26//! `TemperatureMeasurement`, `RelativeHumidityMeasurement`, and `DoorLock`
27//! (Aliro features excluded). M9-A2.1 pilot (decode-smoke tested):
28//! `IlluminanceMeasurement`, `PressureMeasurement`, `FlowMeasurement`,
29//! `BooleanState`, and `Switch`. M9-A2.2 energy (decode-smoke + one nested
30//! byte-parity vector): `PowerSource`, `ElectricalPowerMeasurement`,
31//! `ElectricalEnergyMeasurement`, and `AirQuality`. M9-A2.3 actuators
32//! (roundtrip + decode-smoke, with a byte-parity vector for the list-typed
33//! `AtomicRequest` command): `Thermostat`, `FanControl`,
34//! `ThermostatUserInterfaceConfiguration`, `PumpConfigurationAndControl`, and
35//! `WindowCovering`. M9-A2.4 utility (decode-smoke + one struct-with-byte-fields
36//! byte-parity vector for `GeneralDiagnostics` `NetworkInterface`): `Groups`,
37//! `Binding`, `GeneralDiagnostics`, `FixedLabel`, and `UserLabel`. M9-A2.5
38//! management (codecs only — protocol logic deferred to later milestones;
39//! decode-smoke + a byte-parity vector for the recursive list-of-struct command
40//! encode `AccessControl::ReviewFabricRestrictions`): `AccessControl`,
41//! `GroupKeyManagement`, `AdministratorCommissioning`, and
42//! `OtaSoftwareUpdateRequestor`. Concentration measurement (Matter 1.2, #112 —
43//! decode-smoke per cluster, plus a matter.js byte-parity vector and a
44//! `proptest` wire round-trip for the float attributes they introduce):
45//! `CarbonMonoxide`, `CarbonDioxide`, `NitrogenDioxide`, `Ozone`, `Pm25`,
46//! `Formaldehyde`, `Pm1`, `Pm10`, `TotalVolatileOrganicCompounds`, and
47//! `Radon` `ConcentrationMeasurement`.
48//!
49//! For any attribute not covered by these typed codecs — optional,
50//! manufacturer-specific, or a cluster not in this list — the generic `Value`
51//! path in `matter-controller` remains the universal answer.
52//!
53//! # Usage
54//!
55//! Codecs are free functions per attribute/command. Encoders return a standalone
56//! anonymous-tagged TLV element (ready to embed in an Interaction Model
57//! request); decoders take the attribute value bytes from a report.
58//!
59//! ```
60//! use matter_clusters::gen::{basic_information, on_off};
61//!
62//! // Command payload — embed in an InvokeRequest (see the `control_onoff` example).
63//! let _toggle = on_off::encode_toggle();
64//!
65//! // Attribute roundtrips: encode a value, decode it back.
66//! let tlv = on_off::encode_on_time(30);
67//! assert_eq!(on_off::decode_on_time(&tlv)?, 30);
68//!
69//! let tlv = basic_information::encode_node_label(&"living room".to_string());
70//! assert_eq!(basic_information::decode_node_label(&tlv)?, "living room");
71//! # Ok::<(), matter_clusters::error::ClusterError>(())
72//! ```
73//!
74//! See `crates/matter-commissioning/examples/control_onoff.rs` for an
75//! end-to-end read / toggle / write against a real device.
76//!
77//! # Scope — reading attributes beyond these clusters
78//!
79//! Typed codecs exist for these clusters' **mandatory and optional** attributes
80//! (a device may not implement a given optional attribute — it then returns
81//! `UNSUPPORTED_ATTRIBUTE`). To read attributes of clusters NOT in this set, or
82//! manufacturer-specific attributes, use the generic Interaction Model path:
83//! `matter_interaction::parse_report_data` decodes any attribute to a
84//! `(AttributePath, matter_codec::Value)` pair without a typed codec. A
85//! high-level generic + wildcard read API, and more typed clusters, arrive in
86//! later milestones.
87
88#![forbid(unsafe_code)]
89
90pub mod datatypes;
91pub mod error;
92pub mod types;
93
94pub use datatypes::SemanticTagStruct;
95
96pub mod gen;
97
98#[cfg(test)]
99mod golden;