Skip to content

Commit

Permalink
[Fabric-Admin] Add Device Manager to manage assigned node ID and remo…
Browse files Browse the repository at this point in the history
…te bridge (#33972)

* [Fabric-Admin] Add Device Manager to manage assigned node ID and remote bridge

* Address review comments
  • Loading branch information
yufengwangca authored and pull[bot] committed Sep 3, 2024
1 parent 3a0c184 commit e68b044
Show file tree
Hide file tree
Showing 10 changed files with 525 additions and 21 deletions.
2 changes: 2 additions & 0 deletions examples/fabric-admin/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ static_library("fabric-admin-utils") {
"commands/pairing/OpenCommissioningWindowCommand.h",
"commands/pairing/PairingCommand.cpp",
"commands/pairing/ToTLVCert.cpp",
"device_manager/DeviceManager.cpp",
"device_manager/DeviceManager.h",
]

deps = [ "${chip_root}/src/app:events" ]
Expand Down
3 changes: 3 additions & 0 deletions examples/fabric-admin/commands/clusters/ReportCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "ReportCommand.h"

#include <app/InteractionModelEngine.h>
#include <device_manager/DeviceManager.h>
#include <inttypes.h>

using namespace ::chip;
Expand All @@ -44,6 +45,8 @@ void ReportCommand::OnAttributeData(const app::ConcreteDataAttributePath & path,
}

LogErrorOnFailure(RemoteDataModelLogger::LogAttributeAsJSON(path, data));

DeviceMgr().HandleAttributeChange(path, data);
}

void ReportCommand::OnEventData(const app::EventHeader & eventHeader, TLV::TLVReader * data, const app::StatusIB * status)
Expand Down
4 changes: 3 additions & 1 deletion examples/fabric-admin/commands/fabric-sync/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ void registerCommandsFabricSync(Commands & commands, CredentialIssuerCommands *
const char * clusterName = "FabricSync";

commands_list clusterCommands = {
make_unique<FabricSyncAddDeviceCommand>(credsIssuerConfig),
make_unique<FabricSyncAddBridgeCommand>(credsIssuerConfig),
make_unique<FabricSyncRemoveBridgeCommand>(credsIssuerConfig),
make_unique<FabricSyncDeviceCommand>(credsIssuerConfig),
make_unique<FabricAutoSyncCommand>(credsIssuerConfig),
};

commands.RegisterCommandSet(clusterName, clusterCommands, "Commands for fabric synchronization.");
Expand Down
145 changes: 133 additions & 12 deletions examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "FabricSyncCommand.h"
#include <commands/common/RemoteDataModelLogger.h>
#include <commands/interactive/InteractiveCommands.h>
#include <device_manager/DeviceManager.h>
#include <setup_payload/ManualSetupPayloadGenerator.h>
#include <thread>
#include <unistd.h>
Expand All @@ -36,17 +37,121 @@ constexpr uint32_t kCommissionPrepareTimeMs = 500;
constexpr uint16_t kMaxManaulCodeLength = 21;
constexpr uint16_t kSubscribeMinInterval = 0;
constexpr uint16_t kSubscribeMaxInterval = 60;
constexpr uint16_t kRemoteBridgePort = 5540;

} // namespace

CHIP_ERROR FabricSyncAddDeviceCommand::RunCommand(NodeId remoteId)
void FabricSyncAddBridgeCommand::OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err)
{
#if defined(PW_RPC_ENABLED)
AddSynchronizedDevice(remoteId);
if (mBridgeNodeId != deviceId)
{
ChipLogProgress(NotSpecified, "Commissioning complete for non-bridge device: NodeId: " ChipLogFormatX64,
ChipLogValueX64(deviceId));
return;
}

if (err == CHIP_NO_ERROR)
{
DeviceMgr().SetRemoteBridgeNodeId(mBridgeNodeId);
ChipLogProgress(NotSpecified, "Successfully paired bridge device: NodeId: " ChipLogFormatX64,
ChipLogValueX64(mBridgeNodeId));

char command[kMaxCommandSize];
snprintf(command, sizeof(command), "descriptor subscribe parts-list %d %d %ld %d", kSubscribeMinInterval,
kSubscribeMaxInterval, mBridgeNodeId, kAggragatorEndpointId);

PushCommand(command);
}
else
{
ChipLogError(NotSpecified, "Failed to pair bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT,
ChipLogValueX64(deviceId), err.Format());
}

mBridgeNodeId = kUndefinedNodeId;
}

CHIP_ERROR FabricSyncAddBridgeCommand::RunCommand(NodeId remoteId)
{
if (DeviceMgr().IsFabricSyncReady())
{
// print to console
fprintf(stderr, "Remote Fabric Bridge has been alread configured.");
return CHIP_NO_ERROR;
}

char command[kMaxCommandSize];
snprintf(command, sizeof(command), "pairing already-discovered %ld %d %s %d", remoteId, kSetupPinCode,
reinterpret_cast<const char *>(mRemoteAddr.data()), kRemoteBridgePort);

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

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

pairingCommand->RegisterCommissioningDelegate(this);
mBridgeNodeId = remoteId;

PushCommand(command);

return CHIP_NO_ERROR;
}

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

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

mBridgeNodeId = kUndefinedNodeId;
}

CHIP_ERROR FabricSyncRemoveBridgeCommand::RunCommand()
{
NodeId bridgeNodeId = DeviceMgr().GetRemoteBridgeNodeId();

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

mBridgeNodeId = bridgeNodeId;

char command[kMaxCommandSize];
snprintf(command, sizeof(command), "pairing unpair %ld", mBridgeNodeId);

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

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

pairingCommand->RegisterPairingDelegate(this);

PushCommand(command);

return CHIP_NO_ERROR;
#else
return CHIP_ERROR_NOT_IMPLEMENTED;
#endif
}

void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR err, chip::SetupPayload payload)
Expand All @@ -59,7 +164,7 @@ void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_
if (error == CHIP_NO_ERROR)
{
char command[kMaxCommandSize];
NodeId nodeId = 2; // TODO: (Issue #33947) need to switch to dynamically assigned ID
NodeId nodeId = DeviceMgr().GetNextAvailableNodeId();
snprintf(command, sizeof(command), "pairing code %ld %s", nodeId, payloadBuffer);

PairingCommand * pairingCommand = static_cast<PairingCommand *>(CommandMgr().GetCommandByName("pairing", "code"));
Expand Down Expand Up @@ -101,7 +206,7 @@ void FabricSyncDeviceCommand::OnCommissioningComplete(chip::NodeId deviceId, CHI

if (err == CHIP_NO_ERROR)
{
// TODO: (Issue #33947) Add Synced Device to device manager
DeviceMgr().AddSyncedDevice(Device(mAssignedNodeId, mRemoteEndpointId));
}
else
{
Expand All @@ -112,17 +217,23 @@ void FabricSyncDeviceCommand::OnCommissioningComplete(chip::NodeId deviceId, CHI

CHIP_ERROR FabricSyncDeviceCommand::RunCommand(EndpointId remoteId)
{
if (!DeviceMgr().IsFabricSyncReady())
{
// print to console
fprintf(stderr, "Remote Fabric Bridge is not configured yet.");
return CHIP_NO_ERROR;
}

char command[kMaxCommandSize];
NodeId bridgeNodeId = 1; // TODO: (Issue #33947) need to switch to configured ID
snprintf(command, sizeof(command), "pairing open-commissioning-window %ld %d %d %d %d %d", bridgeNodeId, remoteId,
kEnhancedCommissioningMethod, kWindowTimeout, kIteration, kDiscriminator);
snprintf(command, sizeof(command), "pairing open-commissioning-window %ld %d %d %d %d %d", DeviceMgr().GetRemoteBridgeNodeId(),
remoteId, kEnhancedCommissioningMethod, kWindowTimeout, kIteration, kDiscriminator);

OpenCommissioningWindowCommand * openCommand =
static_cast<OpenCommissioningWindowCommand *>(CommandMgr().GetCommandByName("pairing", "open-commissioning-window"));

if (openCommand == nullptr)
{
return CHIP_ERROR_UNINITIALIZED;
return CHIP_ERROR_NOT_IMPLEMENTED;
}

openCommand->RegisterDelegate(this);
Expand All @@ -131,3 +242,13 @@ CHIP_ERROR FabricSyncDeviceCommand::RunCommand(EndpointId remoteId)

return CHIP_NO_ERROR;
}

CHIP_ERROR FabricAutoSyncCommand::RunCommand(bool enableAutoSync)
{
DeviceMgr().EnableAutoSync(enableAutoSync);

// print to console
fprintf(stderr, "Auto Fabric Sync is %s.\n", enableAutoSync ? "enabled" : "disabled");

return CHIP_NO_ERROR;
}
47 changes: 45 additions & 2 deletions examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,55 @@
#include <commands/pairing/OpenCommissioningWindowCommand.h>
#include <commands/pairing/PairingCommand.h>

constexpr uint32_t kSetupPinCode = 20202021;
constexpr uint16_t kMaxCommandSize = 64;
constexpr uint16_t kDiscriminator = 3840;
constexpr uint16_t kWindowTimeout = 300;
constexpr uint16_t kIteration = 1000;
constexpr uint16_t kAggragatorEndpointId = 1;
constexpr uint8_t kEnhancedCommissioningMethod = 1;

class FabricSyncAddDeviceCommand : public CHIPCommand
class FabricSyncAddBridgeCommand : public CHIPCommand, public CommissioningDelegate
{
public:
FabricSyncAddDeviceCommand(CredentialIssuerCommands * credIssuerCommands) : CHIPCommand("add-device", credIssuerCommands)
FabricSyncAddBridgeCommand(CredentialIssuerCommands * credIssuerCommands) : CHIPCommand("add-bridge", credIssuerCommands)
{
AddArgument("nodeid", 0, UINT64_MAX, &mNodeId);
AddArgument("device-remote-ip", &mRemoteAddr);
}

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 mBridgeNodeId;
chip::ByteSpan mRemoteAddr;

CHIP_ERROR RunCommand(NodeId remoteId);
};

class FabricSyncRemoveBridgeCommand : public CHIPCommand, public PairingDelegate
{
public:
FabricSyncRemoveBridgeCommand(CredentialIssuerCommands * credIssuerCommands) : CHIPCommand("remove-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 mBridgeNodeId;
};

class FabricSyncDeviceCommand : public CHIPCommand, public CommissioningWindowDelegate, public CommissioningDelegate
{
public:
Expand All @@ -69,3 +93,22 @@ class FabricSyncDeviceCommand : public CHIPCommand, public CommissioningWindowDe

CHIP_ERROR RunCommand(chip::EndpointId remoteId);
};

class FabricAutoSyncCommand : public CHIPCommand
{
public:
FabricAutoSyncCommand(CredentialIssuerCommands * credIssuerCommands) : CHIPCommand("enable-auto-sync", credIssuerCommands)
{
AddArgument("state", 0, 1, &mEnableAutoSync, "Set to true to enable auto Fabric Sync, false to disable.");
}

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

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

private:
bool mEnableAutoSync;

CHIP_ERROR RunCommand(bool enableAutoSync);
};
4 changes: 1 addition & 3 deletions examples/fabric-admin/commands/pairing/PairingCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,7 @@ void PairingCommand::OnCurrentFabricRemove(void * context, NodeId nodeId, CHIP_E
// print to console
fprintf(stderr, "Device with Node ID: 0x%lx has been successfully removed.\n", nodeId);

#if defined(PW_RPC_ENABLED)
RemoveSynchronizedDevice(nodeId);
#endif
// TODO: (#33973) Add RPC method RemoveSynchronizedDevice
}
else
{
Expand Down
Loading

0 comments on commit e68b044

Please sign in to comment.