Skip to content

Commit

Permalink
Peer management API (#1252)
Browse files Browse the repository at this point in the history
Formalize the notion of a "peer" (commissioned node on a shared fabric) and restructures logic for dealing with peers:

  - ControllerCommissioner handles commissioning.  It comprises code extracted from MatterController.
  - The previous "ControllerCommissioner" class is now "ControllerCommissioningFlow" and still performs the actual commissioning steps.
  - PeerSet manages operational peers and also consists primarily of code formerly housed in MatterController.
  - PeerAddress is a fabric index/node ID tuple for addressing peers.  Other components that previously worked with only a single fabric or took fabric+node parameters now use this for identifying peers.
  - OperationalPeer is the record managed by PeerSet that describes operational information for a specific PeerAddress.

I created these components in packages/protocol/src/peer and moved ControllerDiscovery there as well.

Co-authored-by: Ingo Fischer <[email protected]>
  • Loading branch information
lauckhart and Apollon77 authored Oct 1, 2024
1 parent d2e06b2 commit 2d9d1cb
Show file tree
Hide file tree
Showing 41 changed files with 1,833 additions and 1,269 deletions.
10 changes: 9 additions & 1 deletion packages/general/src/net/NetInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { Environment } from "#environment/Environment.js";
import { Environmental } from "#environment/Environmental.js";
import { Channel } from "./Channel.js";
import { ServerAddress } from "./ServerAddress.js";
import { TransportInterface, TransportInterfaceSet } from "./TransportInterface.js";
Expand All @@ -22,4 +24,10 @@ export function isNetworkInterface(obj: TransportInterface | NetInterface): obj
/**
* A collection of {@link NetInterfaces} managed as a unit.
*/
export class NetInterfaceSet extends TransportInterfaceSet<NetInterface> {}
export class NetInterfaceSet extends TransportInterfaceSet<NetInterface> {
[Environmental.create](env: Environment) {
const instance = new NetInterfaceSet();
env.set(NetInterfaceSet, this);
return instance;
}
}
4 changes: 4 additions & 0 deletions packages/general/src/util/Set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ export class BasicSet<T, AddT = T> implements ImmutableSet<T>, MutableSet<T, Add
return this.#entries.size;
}

map<R>(mapper: (item: T) => R) {
return [...this].map(mapper);
}

find(predicate: (item: T) => boolean | undefined) {
for (const item of this) {
if (predicate(item)) {
Expand Down
7 changes: 6 additions & 1 deletion packages/general/src/util/Stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
*/
import { MatterError } from "../MatterError.js";

export class EndOfStreamError extends MatterError {}
export class EndOfStreamError extends MatterError {
constructor(message = "Unexpected end of stream") {
super(message);
}
}

export class NoResponseTimeoutError extends MatterError {}

export interface Stream<T> {
Expand Down
49 changes: 7 additions & 42 deletions packages/matter.js/src/CommissioningController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
NetInterfaceSet,
Network,
NoProviderError,
ServerAddress,
StorageContext,
SupportedStorageTypes,
SyncStorage,
Expand All @@ -24,13 +23,14 @@ import {
Ble,
CommissionableDevice,
CommissionableDeviceIdentifiers,
ControllerCommissioningOptions,
ControllerDiscovery,
DiscoveryData,
InteractionClient,
MdnsBroadcaster,
MdnsScanner,
MdnsService,
NodeDiscoveryType,
PeerCommissioningOptions,
ScannerSet,
SupportedAttributeClient,
} from "#protocol";
Expand All @@ -46,7 +46,7 @@ import {
VendorId,
} from "#types";
import { CommissioningControllerNodeOptions, PairedNode } from "./device/PairedNode.js";
import { MatterController, NodeDiscoveryType } from "./MatterController.js";
import { MatterController } from "./MatterController.js";
import { MatterNode } from "./MatterNode.js";

const logger = new Logger("CommissioningController");
Expand Down Expand Up @@ -120,44 +120,8 @@ export type CommissioningControllerOptions = CommissioningControllerNodeOptions

/** Options needed to commission a new node */
export type NodeCommissioningOptions = CommissioningControllerNodeOptions & {
/** Commission related options. */
commissioning?: ControllerCommissioningOptions;

/** Discovery related options. */
discovery: (
| {
/**
* Device identifiers (Short or Long Discriminator, Product/Vendor-Ids, Device-type or a pre-discovered
* instance Id, or "nothing" to discover all commissionable matter devices) to use for discovery.
* If the property commissionableDevice is provided this property is ignored.
*/
identifierData: CommissionableDeviceIdentifiers;
}
| {
/**
* Commissionable device object returned by a discovery run.
* If this property is provided then identifierData and knownAddress are ignored.
*/
commissionableDevice: CommissionableDevice;
}
) & {
/**
* 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<typeof DiscoveryCapabilitiesBitmap>;

/**
* Known address of the device to use for discovery. if this is set this will be tried first before discovering
* the device.
*/
knownAddress?: ServerAddress;

/** Timeout in seconds for the discovery process. Default: 30 seconds */
timeoutSeconds?: number;
};

/** Passcode to use for commissioning. */
commissioning: Omit<PeerCommissioningOptions, "fabric" | "discovery" | "passcode">;
discovery: PeerCommissioningOptions["discovery"];
passcode: number;
};

Expand Down Expand Up @@ -274,7 +238,8 @@ export class CommissioningController extends MatterNode {
}

/**
* Commissions/Pairs a new device into the controller fabric. The method returns the NodeId of the commissioned node.
* Commissions/Pairs a new device into the controller fabric. The method returns the NodeId of the commissioned
* node.
*/
async commissionNode(nodeOptions: NodeCommissioningOptions, connectNodeAfterCommissioning = true) {
this.assertIsAddedToMatterServer();
Expand Down
4 changes: 2 additions & 2 deletions packages/matter.js/src/CommissioningServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,8 @@ export class CommissioningServer extends MatterNode {
randomizationWindowSeconds: this.options.subscriptionRandomizationWindowSeconds,
},
maxPathsPerInvoke,
initiateExchange: (fabric, nodeId, protocolId) => {
return deviceInstance.initiateExchange(fabric, nodeId, protocolId);
initiateExchange: (address, protocolId) => {
return deviceInstance.initiateExchange(address, protocolId);
},
});
deviceInstance.addProtocolHandler(this.interactionServer);
Expand Down
Loading

0 comments on commit 2d9d1cb

Please sign in to comment.