Skip to content

Commit

Permalink
[Fabric-Admin] Add API to commission local bridge within its own fabr…
Browse files Browse the repository at this point in the history
…ic (#35020)

* Add local bridge handle API

* Update examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp

Co-authored-by: saurabhst <[email protected]>

* Update examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp

Co-authored-by: saurabhst <[email protected]>

* Use VerifyOrDie to check pairingCommand

---------

Co-authored-by: saurabhst <[email protected]>
  • Loading branch information
yufengwangca and saurabhst authored Aug 15, 2024
1 parent 6cdd274 commit e8e9fc5
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 15 deletions.
2 changes: 2 additions & 0 deletions examples/fabric-admin/commands/fabric-sync/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ void registerCommandsFabricSync(Commands & commands, CredentialIssuerCommands *
commands_list clusterCommands = {
make_unique<FabricSyncAddBridgeCommand>(credsIssuerConfig),
make_unique<FabricSyncRemoveBridgeCommand>(credsIssuerConfig),
make_unique<FabricSyncAddLocalBridgeCommand>(credsIssuerConfig),
make_unique<FabricSyncRemoveLocalBridgeCommand>(credsIssuerConfig),
make_unique<FabricSyncDeviceCommand>(credsIssuerConfig),
make_unique<FabricAutoSyncCommand>(credsIssuerConfig),
};
Expand Down
121 changes: 110 additions & 11 deletions examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,14 @@ using namespace ::chip;

namespace {

// Constants
constexpr uint32_t kCommissionPrepareTimeMs = 500;
constexpr uint16_t kMaxManaulCodeLength = 21;

void CheckFabricBridgeSynchronizationSupport(intptr_t ignored)
{
DeviceMgr().ReadSupportedDeviceCategories();
}

} // namespace

void FabricSyncAddBridgeCommand::OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err)
void FabricSyncAddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err)
{
if (mBridgeNodeId != deviceId)
{
Expand Down Expand Up @@ -90,15 +86,15 @@ CHIP_ERROR FabricSyncAddBridgeCommand::RunCommand(NodeId remoteId)
if (DeviceMgr().IsFabricSyncReady())
{
// print to console
fprintf(stderr, "Remote Fabric Bridge has been alread configured.");
fprintf(stderr, "Remote Fabric Bridge has already been configured.");
return CHIP_NO_ERROR;
}

PairingCommand * pairingCommand = static_cast<PairingCommand *>(CommandMgr().GetCommandByName("pairing", "already-discovered"));

if (pairingCommand == nullptr)
{
ChipLogError(NotSpecified, "Pairing onnetwork command is not available");
ChipLogError(NotSpecified, "Pairing already-discovered command is not available");
return CHIP_ERROR_NOT_IMPLEMENTED;
}

Expand All @@ -110,7 +106,7 @@ CHIP_ERROR FabricSyncAddBridgeCommand::RunCommand(NodeId remoteId)
return CHIP_NO_ERROR;
}

void FabricSyncRemoveBridgeCommand::OnDeviceRemoved(chip::NodeId deviceId, CHIP_ERROR err)
void FabricSyncRemoveBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err)
{
if (mBridgeNodeId != deviceId)
{
Expand Down Expand Up @@ -150,7 +146,7 @@ CHIP_ERROR FabricSyncRemoveBridgeCommand::RunCommand()

if (pairingCommand == nullptr)
{
ChipLogError(NotSpecified, "Pairing code command is not available");
ChipLogError(NotSpecified, "Pairing unpair command is not available");
return CHIP_ERROR_NOT_IMPLEMENTED;
}

Expand All @@ -161,13 +157,116 @@ CHIP_ERROR FabricSyncRemoveBridgeCommand::RunCommand()
return CHIP_NO_ERROR;
}

void FabricSyncAddLocalBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err)
{
if (mLocalBridgeNodeId != deviceId)
{
if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "Failed to pair non-bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT,
ChipLogValueX64(deviceId), err.Format());
}
else
{
ChipLogProgress(NotSpecified, "Commissioning complete for non-bridge device: NodeId: " ChipLogFormatX64,
ChipLogValueX64(deviceId));
}
return;
}

if (err == CHIP_NO_ERROR)
{
DeviceMgr().SetLocalBridgeNodeId(mLocalBridgeNodeId);
ChipLogProgress(NotSpecified, "Successfully paired local bridge device: NodeId: " ChipLogFormatX64,
ChipLogValueX64(mLocalBridgeNodeId));
}
else
{
ChipLogError(NotSpecified, "Failed to pair local bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT,
ChipLogValueX64(deviceId), err.Format());
}

mLocalBridgeNodeId = kUndefinedNodeId;
}

CHIP_ERROR FabricSyncAddLocalBridgeCommand::RunCommand(NodeId deviceId)
{
if (DeviceMgr().IsLocalBridgeReady())
{
// print to console
fprintf(stderr, "Local Fabric Bridge has already been configured.");
return CHIP_NO_ERROR;
}

PairingCommand * pairingCommand = static_cast<PairingCommand *>(CommandMgr().GetCommandByName("pairing", "already-discovered"));
VerifyOrDie(pairingCommand != nullptr);

pairingCommand->RegisterCommissioningDelegate(this);
mLocalBridgeNodeId = deviceId;

DeviceMgr().PairLocalFabricBridge(deviceId);

return CHIP_NO_ERROR;
}

void FabricSyncRemoveLocalBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err)
{
if (mLocalBridgeNodeId != deviceId)
{
ChipLogProgress(NotSpecified, "A non-bridge device: NodeId: " ChipLogFormatX64 " is removed.", ChipLogValueX64(deviceId));
return;
}

if (err == CHIP_NO_ERROR)
{
DeviceMgr().SetLocalBridgeNodeId(kUndefinedNodeId);
ChipLogProgress(NotSpecified, "Successfully removed local bridge device: NodeId: " ChipLogFormatX64,
ChipLogValueX64(mLocalBridgeNodeId));
}
else
{
ChipLogError(NotSpecified, "Failed to remove local bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT,
ChipLogValueX64(deviceId), err.Format());
}

mLocalBridgeNodeId = kUndefinedNodeId;
}

CHIP_ERROR FabricSyncRemoveLocalBridgeCommand::RunCommand()
{
NodeId bridgeNodeId = DeviceMgr().GetLocalBridgeNodeId();

if (bridgeNodeId == kUndefinedNodeId)
{
// print to console
fprintf(stderr, "Local Fabric Bridge is not configured yet, nothing to remove.");
return CHIP_NO_ERROR;
}

mLocalBridgeNodeId = bridgeNodeId;

PairingCommand * pairingCommand = static_cast<PairingCommand *>(CommandMgr().GetCommandByName("pairing", "unpair"));

if (pairingCommand == nullptr)
{
ChipLogError(NotSpecified, "Pairing unpair command is not available");
return CHIP_ERROR_NOT_IMPLEMENTED;
}

pairingCommand->RegisterPairingDelegate(this);

DeviceMgr().UnpairLocalFabricBridge();

return CHIP_NO_ERROR;
}

void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR err, chip::SetupPayload payload)
{
ChipLogProgress(NotSpecified, "FabricSyncDeviceCommand::OnCommissioningWindowOpened");

if (err == CHIP_NO_ERROR)
{
char payloadBuffer[kMaxManaulCodeLength + 1];
char payloadBuffer[kMaxManualCodeLength + 1];
MutableCharSpan manualCode(payloadBuffer);
CHIP_ERROR error = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualCode);
if (error == CHIP_NO_ERROR)
Expand Down Expand Up @@ -202,7 +301,7 @@ void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_
}
}

void FabricSyncDeviceCommand::OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err)
void FabricSyncDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err)
{
if (mAssignedNodeId != deviceId)
{
Expand Down
47 changes: 46 additions & 1 deletion examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
#include <commands/pairing/OpenCommissioningWindowCommand.h>
#include <commands/pairing/PairingCommand.h>

// Constants
constexpr uint32_t kCommissionPrepareTimeMs = 500;
constexpr uint16_t kMaxManualCodeLength = 21;

class FabricSyncAddBridgeCommand : public CHIPCommand, public CommissioningDelegate
{
public:
Expand All @@ -31,7 +35,7 @@ class FabricSyncAddBridgeCommand : public CHIPCommand, public CommissioningDeleg
AddArgument("device-remote-ip", &mRemoteAddr);
}

void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) override;
void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) override;

/////////// CHIPCommand Interface /////////
CHIP_ERROR RunCommand() override { return RunCommand(mNodeId); }
Expand Down Expand Up @@ -63,6 +67,47 @@ class FabricSyncRemoveBridgeCommand : public CHIPCommand, public PairingDelegate
chip::NodeId mBridgeNodeId;
};

class FabricSyncAddLocalBridgeCommand : public CHIPCommand, public CommissioningDelegate
{
public:
FabricSyncAddLocalBridgeCommand(CredentialIssuerCommands * credIssuerCommands) :
CHIPCommand("add-local-bridge", credIssuerCommands)
{
AddArgument("nodeid", 0, UINT64_MAX, &mNodeId);
}

void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) override;

/////////// CHIPCommand Interface /////////
CHIP_ERROR RunCommand() override { return RunCommand(mNodeId); }

chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(1); }

private:
chip::NodeId mNodeId;
chip::NodeId mLocalBridgeNodeId;

CHIP_ERROR RunCommand(chip::NodeId deviceId);
};

class FabricSyncRemoveLocalBridgeCommand : public CHIPCommand, public PairingDelegate
{
public:
FabricSyncRemoveLocalBridgeCommand(CredentialIssuerCommands * credIssuerCommands) :
CHIPCommand("remove-local-bridge", credIssuerCommands)
{}

void OnDeviceRemoved(chip::NodeId deviceId, CHIP_ERROR err) override;

/////////// CHIPCommand Interface /////////
CHIP_ERROR RunCommand() override;

chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(1); }

private:
chip::NodeId mLocalBridgeNodeId;
};

class FabricSyncDeviceCommand : public CHIPCommand, public CommissioningWindowDelegate, public CommissioningDelegate
{
public:
Expand Down
25 changes: 24 additions & 1 deletion examples/fabric-admin/device_manager/DeviceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ namespace {
// Constants
constexpr uint32_t kSetupPinCode = 20202021;
constexpr uint16_t kRemoteBridgePort = 5540;
constexpr uint16_t kLocalBridgePort = 5540;
constexpr uint16_t kWindowTimeout = 300;
constexpr uint16_t kIteration = 1000;
constexpr uint16_t kSubscribeMinInterval = 0;
Expand Down Expand Up @@ -117,6 +118,8 @@ void DeviceManager::RemoveSyncedDevice(NodeId nodeId)
void DeviceManager::OpenDeviceCommissioningWindow(NodeId nodeId, uint32_t commissioningTimeout, uint32_t iterations,
uint32_t discriminator, const char * saltHex, const char * verifierHex)
{
ChipLogProgress(NotSpecified, "Open the commissioning window of device with NodeId:" ChipLogFormatX64, ChipLogValueX64(nodeId));

// Open the commissioning window of a device within its own fabric.
StringBuilder<kMaxCommandSize> commandBuilder;

Expand All @@ -132,7 +135,7 @@ void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpoin
// Open the commissioning window of a device from another fabric via its fabric bridge.
// This method constructs and sends a command to open the commissioning window for a device
// that is part of a different fabric, accessed through a fabric bridge.
StringBuilder<512> commandBuilder;
StringBuilder<kMaxCommandSize> commandBuilder;

// Use random discriminator to have less chance of collission.
uint16_t discriminator =
Expand Down Expand Up @@ -166,6 +169,16 @@ void DeviceManager::PairRemoteDevice(chip::NodeId nodeId, const char * payload)
PushCommand(commandBuilder.c_str());
}

void DeviceManager::PairLocalFabricBridge(NodeId nodeId)
{
StringBuilder<kMaxCommandSize> commandBuilder;

commandBuilder.Add("pairing already-discovered ");
commandBuilder.AddFormat("%lu %d ::1 %d", nodeId, kSetupPinCode, kLocalBridgePort);

PushCommand(commandBuilder.c_str());
}

void DeviceManager::UnpairRemoteFabricBridge()
{
StringBuilder<kMaxCommandSize> commandBuilder;
Expand All @@ -176,6 +189,16 @@ void DeviceManager::UnpairRemoteFabricBridge()
PushCommand(commandBuilder.c_str());
}

void DeviceManager::UnpairLocalFabricBridge()
{
StringBuilder<kMaxCommandSize> commandBuilder;

commandBuilder.Add("pairing unpair ");
commandBuilder.AddFormat("%lu", mLocalBridgeNodeId);

PushCommand(commandBuilder.c_str());
}

void DeviceManager::SubscribeRemoteFabricBridge()
{
// Listen to the state changes of the remote fabric bridge.
Expand Down
30 changes: 28 additions & 2 deletions examples/fabric-admin/device_manager/DeviceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,20 @@ class DeviceManager : public PairingDelegate

chip::NodeId GetRemoteBridgeNodeId() const { return mRemoteBridgeNodeId; }

chip::NodeId GetLocalBridgeNodeId() const { return mLocalBridgeNodeId; }

void UpdateLastUsedNodeId(chip::NodeId nodeId);

void SetRemoteBridgeNodeId(chip::NodeId remoteBridgeNodeId) { mRemoteBridgeNodeId = remoteBridgeNodeId; }
void SetRemoteBridgeNodeId(chip::NodeId nodeId) { mRemoteBridgeNodeId = nodeId; }

void SetLocalBridgeNodeId(chip::NodeId nodeId) { mLocalBridgeNodeId = nodeId; }

bool IsAutoSyncEnabled() const { return mAutoSyncEnabled; }

bool IsFabricSyncReady() const { return mRemoteBridgeNodeId != chip::kUndefinedNodeId; }

bool IsLocalBridgeReady() const { return mLocalBridgeNodeId != chip::kUndefinedNodeId; }

void EnableAutoSync(bool state) { mAutoSyncEnabled = state; }

void AddSyncedDevice(const Device & device);
Expand Down Expand Up @@ -126,8 +132,20 @@ class DeviceManager : public PairingDelegate
*/
void PairRemoteDevice(chip::NodeId nodeId, const char * payload);

/**
* @brief Pair a local fabric bridge with a given node ID.
*
* This function initiates the pairing process for the local fabric bridge using the specified parameters.
* @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID,
* as for the first fabric.
*/
void PairLocalFabricBridge(chip::NodeId nodeId);

void UnpairRemoteFabricBridge();

void UnpairLocalFabricBridge();

void SubscribeRemoteFabricBridge();

void StartReverseCommissioning();
Expand All @@ -147,8 +165,16 @@ class DeviceManager : public PairingDelegate

static DeviceManager sInstance;

chip::NodeId mLastUsedNodeId = 0;
chip::NodeId mLastUsedNodeId = 0;

// The Node ID of the remote bridge used for Fabric-Sync
// This represents the bridge on the other ecosystem.
chip::NodeId mRemoteBridgeNodeId = chip::kUndefinedNodeId;

// The Node ID of the local bridge used for Fabric-Sync
// This represents the bridge within its own ecosystem.
chip::NodeId mLocalBridgeNodeId = chip::kUndefinedNodeId;

std::set<Device> mSyncedDevices;
bool mAutoSyncEnabled = false;
bool mInitialized = false;
Expand Down

0 comments on commit e8e9fc5

Please sign in to comment.