/** * @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 { Endpoint } from "#endpoint/Endpoint.js"; import { AsyncObservable, AsyncObservableValue, Bytes, Duration, Observable, Observer, Timestamp } from "@matter/general"; import { PeerAddress, type FabricIcd } from "@matter/protocol"; import { SubjectId, VendorId } from "@matter/types"; import { IcdManagement } from "@matter/types/clusters/icd-management"; /** * Controller-side client for ICD (Intermittently Connected Device) Check-In support. * * Auto-installed on a {@link ClientNode} whose peer exposes the IcdManagement cluster. Registration — automatic for a * LIT-operating peer, or explicit via {@link register} — requires an established subscription so the decision runs on a * fresh operating mode rather than a stale cached one. The behavior tracks peer wakefulness to hold interactions for a * sleeping ICD. * * @see {@link MatterSpecification.v16.Core} § 9.15.1, § 9.16 */ export declare class IcdClient extends Behavior { #private; internal: IcdClient.Internal; readonly state: IcdClient.State; readonly events: IcdClient.Events; static readonly early = true; static readonly id = "icd"; get isRegistered(): boolean; /** Whether the peer is LIT-capable (LongIdleTimeSupport feature and specification version >= 1.4.0). */ get peerSupportsLit(): boolean; /** * Whether the peer is currently awake. A non-LIT or not-yet-fed peer has nothing to await and reads true. */ get awake(): any; /** * Deadline by which the next Check-In from a registered LIT peer is expected, or undefined when no Check-In is * scheduled (no fed peer / not registered / not LIT). Derived from the fed peer's wakefulness availability window. */ get nextExpectedCheckin(): Timestamp | undefined; initialize(): void; /** * Register this controller as a Check-In client on the peer. * * Installs a shared {@link IcdManagement.RegisterClientRequest.key} on the peer so it can send us encrypted * Check-In messages, records the rolling-counter baseline in {@link IcdClient.State}, and arms the controller-side Check-In * receive path on the fabric. * * @throws {ImplementationError} if the peer is not online (registration reads from and writes to the peer), or its * IcdManagement cluster lacks the Check-In Protocol feature. * @throws {IcdMultiAdminError} if the peer has more than one administrator from other vendors and * `allowMultiAdmin` is not set — see {@link IcdMultiAdminError.assertSingleAdmin}. */ register(options?: { monitoredSubject?: SubjectId; clientType?: IcdManagement.ClientType; allowMultiAdmin?: boolean; ignoredVendors?: VendorId[]; }): Promise; /** * Remove this controller's Check-In registration from the peer and tear down the local receive path. * * Best-effort on the peer: local state is cleared even if the peer {@link IcdManagement.unregisterClient} fails (it * may be unreachable). A no-op when not registered. */ unregister(): Promise; /** * Locally drop this controller's Check-In registration without contacting the peer. * * Escape hatch for an unreachable registered LIT peer: {@link unregister} round-trips to the peer, so it parks on * the same wakefulness deadlock this clears. Dropping the fed peer removes its wakefulness, so subsequent * interactions no longer hold — a later subscribe can re-establish and re-register. The peer keeps a stale * registration for us until it prunes it (or a fresh {@link register} mints a new key). A no-op when not registered. */ forget(): Promise; /** * Ask the peer to remain in Active mode for at least `duration` and return the duration it actually promised. * * @see {@link MatterSpecification.v16.Core} § 9.16.7.4 */ stayActive(duration: Duration): Promise; /** * Wait for an in-flight key refresh to finish on teardown — aborting between the peer re-key and our state write * would leave the controller and peer with mismatched keys. */ [Symbol.asyncDispose](): Promise; } export declare namespace IcdClient { /** Minimum device Matter specification version (BasicInformation, encoded 0xMMmmpprr) for trustworthy LIT behavior. */ const MIN_LIT_SPECIFICATION_VERSION = 17039360; /** * Whether a peer is LIT-capable: advertises LongIdleTimeSupport AND reports Matter specification version >= 1.4.0. * Devices below 1.4.0 (or not reporting a version) are treated as non-LIT regardless of the feature flag. */ function litSupported(endpoint: Endpoint): boolean; class Internal { /** Retained across re-registrations so the protocol RX path stays armed without creating a second closure. */ checkInHandler?: FabricIcd.CheckInHandler; /** In-flight key refresh; tracked so a second refreshNeeded Check-In can't overlap it and teardown can await it. */ keyRefresh?: Promise; /** In-flight LIT auto-registration; tracked so overlapping triggers can't double-register and teardown can await it. */ autoRegister?: Promise; /** Set when a trigger arrives while {@link autoRegister} is in flight, so it re-evaluates on completion. */ autoRegisterPending?: boolean; /** Address of the peer fed to {@link FabricIcd}; lets decommission drop it after peerAddress is already gone. */ fedPeer?: PeerAddress; /** The fed peer's wakefulness `available` observable we currently mirror; recreated on every feed. */ availableSource?: AsyncObservableValue<[boolean]>; /** Listener mirroring {@link availableSource} into {@link IcdClient.State.available}; removed on drop and before re-feed. */ availableListener?: Observer<[boolean]>; /** The fed peer's wakefulness `checkInMissed` observable we currently mirror; recreated on every feed. */ checkInMissedSource?: AsyncObservable<[]>; /** Listener mirroring {@link checkInMissedSource} into {@link IcdClient.Events.checkInMissed}; removed on drop and before re-feed. */ checkInMissedListener?: Observer<[]>; } class State { /** * Shared secret installed on the peer at registration, used to verify Check-In message ICD counters. */ key?: Bytes; /** * ICD counter value the peer reported at registration; Check-In counters are validated relative to this. */ counterStart?: number; /** * Offset of the most recently observed Check-In counter from {@link counterStart}. */ lastOffset?: number; /** * Subject the peer monitors on our behalf (the node ID notified on Check-In). */ monitoredSubject?: SubjectId; /** * Client type registered with the peer (permanent or ephemeral). */ clientType?: IcdManagement.ClientType; /** * Whether this controller is currently registered as a Check-In client on the peer. */ registered: boolean; /** * Time of the most recently received Check-In from the peer. */ lastCheckInReceivedAt?: Timestamp; /** * Whether the peer is reachable (within its expected Check-In window). Non-LIT peers are always available. */ available: boolean; } class Events extends BaseEvents { registered: Observable; unregistered: Observable; checkedIn: Observable<[checkIn: { counter: number; activeModeThreshold: number; }], void>; keyRefreshed: Observable; available$Changed: Observable<[value: boolean, oldValue: boolean], void>; /** Emits when a registered LIT peer misses its expected Check-In (its availability window lapsed). */ checkInMissed: Observable; } } //# sourceMappingURL=IcdClient.d.ts.map