Host ports¶
A host reaches the module through ports: interfaces it implements, configuration fields it fills, and calls that attach a collaborator. This page lists them by where they live. For each port it says what the port does and what happens when you leave it out.
Two failure modes recur, and they are not interchangeable:
- Fails closed: the request is refused. A controller at least sees a denial.
- Silent: the reply looks well-formed, and the missing behaviour never shows up as an error anywhere.
Source: bridge/bridge.go:38-47.
contract/: what a device and a server implement¶
contract/ imports the standard library only. A host type that implements
these interfaces does not drag the host's dependencies into the module.
Endpoints and cluster servers¶
| Interface | Implemented by | What it does | When absent |
|---|---|---|---|
EndpointSource |
a host device | device type and cluster servers of one bridged endpoint | the source is not an endpoint |
ClusterServer |
every server | read, write, invoke; the reportable attributes | required |
FabricScopedReader |
a server with fabric-scoped attributes | read with the FabricFiltered flag and the reading fabric | MatterRead answers with the full value |
ClusterAttributeLister |
a server | the attribute set, for wildcard reads and AttributeList | a wildcard read returns only the global attributes |
ClusterCommandLister |
a server | AcceptedCommandList and GeneratedCommandList | both lists are empty |
ClusterEventLister |
a server | EventList | EventList is empty |
ClusterDataVersion |
a server | the cluster's DataVersion | the IM layer stamps a constant 1 |
ClusterAttributeReadPrivilege |
a server | a read privilege above View | View |
ClusterAttributeWritePrivilege |
a server | a write privilege above Operate | Operate |
ClusterCommandInvokePrivilege |
a server | an invoke privilege above Operate | Operate |
TimedCommander |
a server | which commands need a timed interaction | the generated table (schema.IsTimedInvoke) decides |
ClusterQuiescer |
a server with its own timers | stops the timers when the server leaves the topology or the bridge stops | timers outlive the server's use |
EventReceiver |
a server that emits events | receives the bridge's EventEmitter at assembly |
the server cannot emit events |
Change reporting¶
| Interface | Implemented by | What it does | When absent |
|---|---|---|---|
AttributeChangeNotifier |
a server that holds its state | names exactly the attributes that changed; the bridge advances the DataVersion and reports only those | see ChangeNotifier |
SelfReportedAttributeLister |
an AttributeChangeNotifier |
attributes it reports only itself (quieter "Q" attributes) | the before/after comparison after a command includes them |
ChangeNotifier |
a host source | "something changed": every reportable attribute of the cluster is marked dirty | silent: subscriptions carry only empty keep-alives, and Apple Home shows the sensor as not responding |
Measurements and classification¶
| Interface | Implemented by | What it does | When absent |
|---|---|---|---|
MeasurementSource |
a host sensor | its measurement class; the assembler picks the cluster and the device type | the source is no measurement |
FloatMeasurementSource, BoolMeasurementSource |
a host sensor | the reading, and whether one was observed yet | — |
ElectricalReadings |
a host meter | the consolidated electrical readings | — |
MeasurementMaterializer |
a host (with RegisterMeasurementKind) |
the servers of a measurement kind the module does not ship | — |
EligibilitySource |
a host model | whether and how fully a data point maps to Matter | the classifier treats it as unmappable |
SwitchEventEmitter |
the module (cluster/switch.Server) |
the press gestures a host narrates (InitialPress, ShortRelease, LongPress, LongRelease); handed to a source with WireMatterSwitchHandler |
— |
SwitchPositionSink |
the module (cluster/switch.Server) |
the positions a host reports (SetRawPosition debounced, SetCurrentPosition); the server derives every Switch event, multi press included, as matter.js SwitchServer.ts does; handed to a source with WireMatterSwitchPositions |
a source without either method reports no press |
Source: contract/doc.go:4-18, contract/matter.go:21-260, contract/matter.go:299-440, contract/matter.go:572-830, contract/switchevents.go:26, contract/switchevents.go:54.
node.Config: the facade's ports¶
| Field | What it does | When nil or zero |
|---|---|---|
Store |
DB, or both Credentials and Endpoints |
New refuses the configuration |
Advertiser |
publishes the node over DNS-SD | mdns.NewNoop(). Nothing is discoverable; the bridge logs matter.mdns.commissioning_not_advertised |
Attestation |
DAC, PAI and Certification Declaration | the CSA test chain and test CD: pairable everywhere, not shippable |
OTA (OtaConfig) |
mounts the OTA Software Update Requestor; Applier carries out an update |
no requestor. A nil Applier is the facade's own, which validates the image and keeps it under Dir/applied |
OTAProvider |
serves OTA images over BDX from an OtaProvider endpoint | no provider (also with a nil ImageSource). A nil Consent declines an image that needs consent; a nil ApplyPolicy proceeds at once |
CommissionerControl |
mounts CommissionerControl on the Aggregator; Approver and Commissioner are required |
no server |
Network.WiFi.Reporter |
mounts WiFiNetworkDiagnostics and states the RootNode condition WiFi | no Wi-Fi diagnostics. EthernetNetworkDiagnostics is always mounted, with every link value null |
Client |
the node's client stack, which the Binding entries reach other nodes through | no client stack. A Binding entry that names a node is dropped |
EndpointPersistence |
scene tables and bridged NodeLabels, kept by the host | the facade's own, in the settings table |
Groups |
the group state, for a host with its own assembler | the facade builds one over the credential store |
Topology |
the host's own bridge.Snapshotter |
the facade's Aggregator under one scope |
AggregatorServers |
extra servers on the Aggregator (an Actions server, say) | none |
Observers |
the host's callbacks on fabric, commissioning and window events | nothing observes. An observer's error or panic is logged, never returned |
Logger |
the node's logger | slog.Default() |
Ports the facade leaves to the host are reached through Node.Root() and
Node.Bridge():
- the GeneralDiagnostics TestEventTrigger enable key;
- the PowerSource endpoints of PowerSourceConfiguration;
- the bridge's
SetOnReassembledandSetOnFabricAddedhooks.
Setting a cluster hook that the facade wires itself, such as
OperationalCredentials SetOnFabricRemoved, replaces the facade's wiring.
Use Observers instead.
Source: node/config.go:28-139, node/config.go:155-193, node/config.go:281-311, node/client.go:29-47, node/ota_provider.go:25-39, node/commissioner_control.go:23-34, node/observers.go:4-65, node/persist.go:55-75, node/root.go:336-347, node/root.go:477-481, node/doc.go:49-64, bridge/bridge.go:1975-1987.
bridge: the Attach… and Set… ports¶
The facade attaches all of these. A host that drives bridge/ directly
attaches them itself, in this order. bridge.New installs a no-op for each
port that is not attached.
Before Start¶
These are read once at Start, or feed a component Start builds.
| Port | Failure mode | What a skip costs |
|---|---|---|
AttachACLLister |
fails closed | every fabric-scoped request is denied with UnsupportedAccess. endpoint.UnenforcedACL is the explicit way to run without an ACL |
AttachSessionLookup |
silent | every encrypted datagram is dropped. CASE completes and carries no traffic |
AttachPaseHandlerProvider (or AttachPaseHandler) |
fails closed | commissioning cannot begin. Prefer the provider: the singleton serialises commissioners |
AttachCaseHandlerProvider (or AttachCaseHandler) |
fails closed | no CASE. A singleton rejects the parallel CASE sessions Apple Home opens |
AttachAckTracker |
silent | no standalone ACKs and no retransmission of the bridge's own messages; every reply is best-effort. It wraps the lower-level AttachAckHandler |
AttachSubscriptionManager |
silent | a Subscribe returns its initial report with no subscription id, and no report follows |
AttachSessionRegistry |
silent | CloseSession closes nothing, Stop sends no farewell, and the re-announce trigger is not installed |
AttachSubscriptionStore |
silent | nothing survives a restart; controllers wait out their liveness timeout. SetSubscriptionPersistence(false) switches persistence off on purpose |
Cluster surface¶
Attaching republishes onto the live topology immediately, as well as on
the next Reassemble.
| Port | Failure mode | What a skip costs |
|---|---|---|
AttachRootClusters, then AttachAggregatorClusters |
silent for wildcards | a wildcard read skips the empty endpoint, so the bridge looks present and empty |
AttachRootPartsListProvider, AttachAggregatorPartsListProvider |
silent | must follow their cluster call. They return false when no Descriptor is mounted, and PartsList stays frozen |
Group communication¶
| Port | Failure mode | What a skip costs |
|---|---|---|
AttachGroupMessaging |
fails closed, silently | every group message is dropped and no multicast group is joined |
AttachAuxiliaryACL |
fails closed, silently | auxiliary ACL entries are listed but not enforced, and group commands relying on them are dropped |
Optional¶
| Port | What a skip costs |
|---|---|
AttachCommissioningWindow |
only Bridge.CommissioningWindow() returns nothing |
AttachCaseInitiatorProvider, AttachOperationalResolver (+ ReestablishFormerSubscriptions) |
former subscriptions are dropped at restart (silent) |
AttachBDXResponder |
BDX exchanges are dropped; an OTA download fails (fails closed) |
AttachDiagnosticEvents |
Bridge.DiagnosticEvents stays empty |
SetOnReassembled, SetOnFabricAdded, SetOnFabricRemoved |
nil-safe observer hooks |
SetDeviceTypeValidation |
warn mode: each new violation is logged once; strict refuses; off judges only singleton placement |
Source: bridge/bridge.go:29-177, bridge/securechannel.go:243-263, bridge/ackpump.go:36-58.
Optional interfaces of cluster ports¶
Some cluster servers take a host port and look for more capabilities on it by type assertion.
| Interface | On | What it does | When absent |
|---|---|---|---|
levelcontrol.NativeRamp |
the device behind levelcontrol.NewNativeSource |
ramps its level by itself; the source keeps Options and OnLevel and turns each command into one target and one duration | — (it is the port) |
levelcontrol.NativeMover |
a NativeRamp |
replaces the Move logic; a device for which a jump to the bound means nothing (a speaker's volume) keeps its level | the source ramps to the bound |
levelcontrol.NativeSwitcher |
a NativeRamp |
writes On/Off and level together (SwitchOn(level, d), SwitchOff(d)); the source then leaves the OnOff attribute to the host |
matter.js's order: switch on, then ramp; ramp down, then switch off |
mdns.Reannouncer |
the Advertiser |
the periodic re-announce loop (30 min default) and Node.TriggerReannounce |
no loop; TriggerReannounce is a no-op |
mdns.Enabled |
the Advertiser |
says whether it publishes at all | mdns.IsEnabled takes the advertiser at its word |
onoff.Sink |
onoff.Config.Sink |
consents to every OnOff change before it is stored; an error answers FAILURE | changes are stored without asking |
Host ports of the root servers, reached through node.Config or
Node.Root():
| Port | What it does |
|---|---|
core.WiFiReporter |
the Wi-Fi link values; the module ships no reporter |
core.OtaApplier |
the host's part of an OTA update |
core.OTAImageSource, core.OTAConsent, core.OTAApplyPolicy |
the provider's catalogue, user consent, and apply decision |
core.CommissioningApprover, core.ReverseCommissioner |
CommissionerControl's approval, and the commissioning of the approved node |
core.ActionsHost |
an Actions server's lists and commands |
core.LogProvider |
DiagnosticLogs content. The facade serves its diagnostic event ring |
Source: cluster/levelcontrol/native.go:15-70, mdns/reannounce.go:15-55, node/reannounce.go:15-50, node/config.go:164-179, cluster/onoff/server.go:54-72, cluster/core/wifi_network_diagnostics.go:26-28, cluster/core/ota_software_update_requestor.go:171, cluster/core/ota_provider.go:93-135, cluster/core/commissioner_control.go:72-110, cluster/core/actions.go:63, cluster/core/diagnostic_logs.go:55-60, node/node.go:714-720.