/** * @license * Copyright 2022-2026 Matter.js Authors * SPDX-License-Identifier: Apache-2.0 */ import { Behavior } from "#behavior/Behavior.js"; import { Events as BaseEvents } from "#behavior/Events.js"; import type { ClientNode } from "#node/ClientNode.js"; import { ClassExtends, Duration, Observable, ServerAddress, Timestamp } from "@matter/general"; import type { SupportedTransportsBitmap } from "@matter/protocol"; import { CommissioningMode, ControllerCommissioningFlow, ControllerCommissioningFlowOptions, DeviceAttestationValidator, DiscoveryData, Fabric, FabricAuthority, PeerTimingParameters, PeerAddress as ProtocolPeerAddress, SessionParameters as ProtocolSessionParameters, Subscribe } from "@matter/protocol"; import { CaseAuthenticatedTag, DeviceTypeId, DiscoveryCapabilitiesBitmap, FabricIndex, NodeId, TypeFromPartialBitSchema, VendorId } from "@matter/types"; import { RemoteDescriptor } from "./RemoteDescriptor.js"; /** * Client functionality related to commissioning. * * Updates node state based on commissioning status and commissions new nodes. */ export declare class CommissioningClient extends Behavior { #private; internal: CommissioningClient.Internal; readonly state: CommissioningClient.State; readonly events: CommissioningClient.Events; static readonly early = true; static readonly id = "commissioning"; initialize(options: { descriptor?: RemoteDescriptor; }): void; [Symbol.asyncDispose](): void; commission(passcode: number | string): Promise; commission(options: CommissioningClient.CommissioningOptions): Promise; /** * Remove this node from the fabric. * * After removal the {@link ClientNode} remains intact. You can use {@link ClientNode#delete} to remove the node * permanently. * * Only legal if this node controls the peer's fabric. */ decommission(): Promise; /** * Override to implement CASE commissioning yourself. * * If you override, matter.js commissions to the point where commissioning over PASE is complete. You must then * complete commissioning yourself by connecting to the device and invoking the "CommissioningComplete" command. */ protected finalizeCommissioning(_address: ProtocolPeerAddress, _discoveryData?: DiscoveryData): Promise; get descriptor(): RemoteDescriptor | undefined; set descriptor(descriptor: RemoteDescriptor | undefined); } export declare namespace CommissioningClient { /** * Concrete version of {@link ProtocolPeerAddress}. */ class PeerAddress implements ProtocolPeerAddress { fabricIndex: FabricIndex; nodeId: NodeId; constructor(fabricIndex: FabricIndex, nodeId: NodeId); } /** * Supported transport flags. */ class SupportedTransports implements Partial { tcpClient?: boolean; tcpServer?: boolean; } /** * Concrete version of {@link ProtocolSessionParameters}. */ class SessionParameters implements Partial { idleInterval?: Duration; activeInterval?: Duration; activeThreshold?: Duration; dataModelRevision?: number; interactionModelRevision?: number; specificationVersion?: number; maxPathsPerInvoke?: number; supportedTransports?: SupportedTransports; maxTcpMessageSize?: number; } /** * The network address of a node. */ class NetworkAddress { type: "udp" | "tcp" | "ble"; ip?: string; port?: number; peripheralAddress?: string; ttl?: Duration | undefined; discoveredAt?: Timestamp | undefined; constructor(address: NetworkAddress); } class Internal { peerObserver?: Disposable; } class State { /** * Fabric index and node ID for paired peers. If this is undefined the node is uncommissioned. */ peerAddress?: PeerAddress; /** * Case Authenticated Tags (CATs) * * See {@link PeerDescriptor} */ caseAuthenticatedTags?: readonly CaseAuthenticatedTag[]; /** * Known network addresses for the device. If this is undefined, the node has not been located on any network * interface. */ addresses?: ServerAddress[]; /** * Time at which the device was discovered. */ discoveredAt?: Timestamp; /** * Time at which we discovered the device's current operational addresses. */ onlineAt?: Timestamp; /** * Time at which we concluded the device's current operational address is unreachable. */ offlineAt?: Timestamp; /** * Time at which the device was commissioned. */ commissionedAt?: Timestamp; /** * Fabric index the peer assigned to our identity (from the AddNoc response). Substituted for the * {@link FabricIndex.OMIT_FABRIC} sentinel on fabric-scoped struct writes so the local cache mirrors * the value the peer will store. * * Distinct from {@link peerAddress.fabricIndex} which is our local fabric index. */ fabricIndexOnPeer?: FabricIndex; /** * The TTL of the discovery record if applicable (in seconds). */ ttl?: Duration; /** * The canonical global ID of the device. */ deviceIdentifier?: string; /** * The device's long discriminator. */ discriminator?: number; /** * The last know commissioning mode of the device. */ commissioningMode?: CommissioningMode; /** * Vendor. */ vendorId?: VendorId; /** * Product. */ productId?: number; /** * Advertised device type. */ deviceType?: DeviceTypeId; /** * The advertised device name specified by the user. */ deviceName?: string; /** * An optional manufacturer-specific unique rotating ID for uniquely identifying the device. */ rotatingIdentifier?: string; /** * A bitmap indicating how to transition the device to commissioning mode from its current state. */ pairingHint?: number; /** * Textual pairing instructions associated with pairing hint. */ pairingInstructions?: string; /** * The remote node's session intervals. */ sessionParameters?: SessionParameters; /** * TCP support bitmap. */ tcpSupport?: number; /** * Indicates whether node is ICD with a slow (15 s+) polling interval. */ longIdleTimeOperatingMode?: boolean; } class Events extends BaseEvents { peerAddress$Changed: Observable<[value: ProtocolPeerAddress | undefined, oldValue: ProtocolPeerAddress | undefined], void>; addresses$Changed: Observable<[value: ServerAddress[] | undefined, oldValue: ServerAddress[] | undefined], void>; caseAuthenticatedTags$Changed: Observable<[value: CaseAuthenticatedTag[] | undefined, oldValue: CaseAuthenticatedTag[] | undefined], void>; } /** * Options that control commissioning. */ interface BaseCommissioningOptions { /** * The ID to assign the node during commissioning. By default the node receives the next available ID. */ nodeId?: NodeId; /** * The fabric the node joins upon commissioning. Defaults to the default fabric of the assigned * {@link FabricAuthority}. */ fabric?: Fabric; /** * The authority controlling the commissioning fabric. Defaults to the {@link FabricAuthority} of the local * environment. */ fabricAuthority?: FabricAuthority; /** * Custom commissioning flow implementation to use instead of the default. */ commissioningFlowImpl?: ClassExtends; /** * Abort signal for cancellation. When fired during PASE establishment, cancels the PASE attempt. * In parallel commissioning scenarios this fires once a winner is found, stopping remaining candidates. */ abort?: AbortSignal; /** * Called immediately after PASE is established, before the main commissioning flow begins. * * Return `true` to proceed with commissioning (this candidate won the parallel race). * Return `false` to abort cleanly — the PASE session is closed and commissioning stops. * * When omitted, commissioning always proceeds. */ continueCommissioningAfterPase?: () => boolean; /** * Overall wall-clock budget for PASE establishment. * Defaults to 30 seconds. */ timeout?: Duration; /** * Discovery capabilities to use for discovery. These are included in the QR code normally and defined if BLE * is supported for initial commissioning. */ discoveryCapabilities?: TypeFromPartialBitSchema; /** * The initial read/subscription used to populate node data. * * By default, matter.js reads all attributes on the node. This allows us to efficiently initialize the complete * node structure. * * If you only require a subset of attributes you can replace this with a more discriminative read. For * example, if you are only interested in interacting with the root endpoint and the On/Off cluster on other * endpoints, you could do: * * ```js * { * defaultSubscription: Read( * Read.Attribute({ endpoint: 0 }), * Read.Attribute({ cluster: OnOffCluster }) * ) * } * ``` * * Note that certain clusters like Descriptor and Basic Information contain critical operational data. If your * read omits them then the node will only be partially functional once initialized. */ defaultSubscription?: Subscribe; /** * By default, nodes we commission are automatically subscribed to using the {@link defaultSubscription} (or a * full wildcard subscription if that is undefined). * * Matter.js will not subscribe automatically if set to false. */ autoSubscribe?: boolean; /** * By default a newly-commissioned node performs a one-time read of its structure so its state is available * immediately, even when {@link autoSubscribe} is false. Set to false to skip this read and leave the node * uninitialized until a later subscription or read. */ autoStateInitialize?: boolean; /** * Case Authenticated Tags (CATs) */ caseAuthenticatedTags?: CaseAuthenticatedTag[]; /** * Controls behavior when device attestation produces findings. * See {@link ControllerCommissioningFlowOptions.onAttestationFailure} for details. */ onAttestationFailure?: DeviceAttestationValidator.OnAttestationFailure; /** * WiFi network credentials to configure on the device during commissioning. Required if the device connects * to the network over WiFi and doesn't already have credentials configured. */ wifiNetwork?: ControllerCommissioningFlowOptions["wifiNetwork"]; /** * Thread network credentials to configure on the device during commissioning. Required if the device connects * to the network over Thread and doesn't already have credentials configured. */ threadNetwork?: ControllerCommissioningFlowOptions["threadNetwork"]; /** * The regulatory location (indoor or outdoor) where the device is used. * Defaults to `Indoor` if not provided. */ regulatoryLocation?: ControllerCommissioningFlowOptions["regulatoryLocation"]; /** * The two-character country code where the device is deployed (e.g. "DE", "US"). * Defaults to "XX" (unspecified). */ regulatoryCountryCode?: ControllerCommissioningFlowOptions["regulatoryCountryCode"]; /** * Override the final commissioning step. * * When provided, matter.js completes commissioning over PASE and then calls this function instead of performing * the CASE reconnection and "CommissioningComplete" command internally. The function must connect to the device * operationally and invoke "CommissioningComplete" itself. * * This is used by {@link PaseCommissioner} so that a lightweight commissioner can perform the PASE phase and * then hand off to a full controller to finish commissioning. * TODO: Revisit when we decide how to continue with the PaseCommissioner approach at all */ finalizeCommissioning?: (address: ProtocolPeerAddress, discoveryData?: DiscoveryData) => Promise; /** * Timing overrides for the step-18 CASE reconnect. * * After commissioning the commissioner establishes the first operational CASE session. The device is freshly * online at that point so tighter timing is appropriate. Any fields provided here are merged on top of the * global peer timing defaults for that single connection only. * * Defaults to `{ delayBeforeNextAddress: Seconds(15), maxDelayBetweenInitialContactRetries: Seconds(60), delayAfterPeerError: Minutes(2) }`. */ caseConnectionTiming?: Partial; } interface PasscodeOptions extends BaseCommissioningOptions { /** * The device's passcode. */ passcode: number; /** * The device's long discriminator. */ discriminator?: number; } interface PairingCodeOptions extends BaseCommissioningOptions { /** * The device's pairing code. */ pairingCode: string; } type CommissioningOptions = PasscodeOptions | PairingCodeOptions; function PasscodeOptions(options: T): T & PasscodeOptions; } //# sourceMappingURL=CommissioningClient.d.ts.map