diff --git a/examples/fabric-admin/BUILD.gn b/examples/fabric-admin/BUILD.gn index 9ab444d5f8dc9c..3427c6c0f6c2d9 100644 --- a/examples/fabric-admin/BUILD.gn +++ b/examples/fabric-admin/BUILD.gn @@ -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" ] diff --git a/examples/fabric-admin/commands/clusters/ReportCommand.cpp b/examples/fabric-admin/commands/clusters/ReportCommand.cpp index b89ec0809433bc..8eb2cc7c33ae0d 100644 --- a/examples/fabric-admin/commands/clusters/ReportCommand.cpp +++ b/examples/fabric-admin/commands/clusters/ReportCommand.cpp @@ -19,6 +19,7 @@ #include "ReportCommand.h" #include +#include #include using namespace ::chip; @@ -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) diff --git a/examples/fabric-admin/commands/fabric-sync/Commands.h b/examples/fabric-admin/commands/fabric-sync/Commands.h index f277c28f9d15b4..94de1d31d8ba09 100644 --- a/examples/fabric-admin/commands/fabric-sync/Commands.h +++ b/examples/fabric-admin/commands/fabric-sync/Commands.h @@ -26,8 +26,10 @@ void registerCommandsFabricSync(Commands & commands, CredentialIssuerCommands * const char * clusterName = "FabricSync"; commands_list clusterCommands = { - make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), }; commands.RegisterCommandSet(clusterName, clusterCommands, "Commands for fabric synchronization."); diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp index 381dc50c83018b..3e050e90904867 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp @@ -19,6 +19,7 @@ #include "FabricSyncCommand.h" #include #include +#include #include #include #include @@ -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(mRemoteAddr.data()), kRemoteBridgePort); + + PairingCommand * pairingCommand = static_cast(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(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) @@ -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(CommandMgr().GetCommandByName("pairing", "code")); @@ -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 { @@ -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(CommandMgr().GetCommandByName("pairing", "open-commissioning-window")); if (openCommand == nullptr) { - return CHIP_ERROR_UNINITIALIZED; + return CHIP_ERROR_NOT_IMPLEMENTED; } openCommand->RegisterDelegate(this); @@ -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; +} diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h index 7b8f6f938afec9..038094583c8554 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h @@ -22,20 +22,25 @@ #include #include +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); } @@ -43,10 +48,29 @@ class FabricSyncAddDeviceCommand : public CHIPCommand 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: @@ -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); +}; diff --git a/examples/fabric-admin/commands/pairing/PairingCommand.cpp b/examples/fabric-admin/commands/pairing/PairingCommand.cpp index 521325a796dce0..5a02739232b054 100644 --- a/examples/fabric-admin/commands/pairing/PairingCommand.cpp +++ b/examples/fabric-admin/commands/pairing/PairingCommand.cpp @@ -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 { diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp new file mode 100644 index 00000000000000..4ea0b033c47c7f --- /dev/null +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -0,0 +1,219 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "DeviceManager.h" + +#include + +#include +#include + +using namespace chip; +using namespace chip::app::Clusters; + +// Define the static member +DeviceManager DeviceManager::sInstance; + +void DeviceManager::Init() +{ + // TODO: (#34113) Init mLastUsedNodeId from chip config file + mLastUsedNodeId = 1; +} + +NodeId DeviceManager::GetNextAvailableNodeId() +{ + mLastUsedNodeId++; + VerifyOrDieWithMsg(mLastUsedNodeId < std::numeric_limits::max(), NotSpecified, "No more available NodeIds."); + + return mLastUsedNodeId; +} + +void DeviceManager::UpdateLastUsedNodeId(chip::NodeId nodeId) +{ + if (nodeId > mLastUsedNodeId) + { + ChipLogProgress(NotSpecified, "Updating last used NodeId to " ChipLogFormatX64, ChipLogValueX64(nodeId)); + mLastUsedNodeId = nodeId; + } +} + +void DeviceManager::AddSyncedDevice(const Device & device) +{ + mSyncedDevices.insert(device); + ChipLogProgress(NotSpecified, "Added synced device: NodeId:" ChipLogFormatX64 ", EndpointId %u", + ChipLogValueX64(device.GetNodeId()), device.GetEndpointId()); +} + +Device * DeviceManager::FindDeviceByEndpoint(EndpointId endpointId) +{ + for (auto & device : mSyncedDevices) + { + if (device.GetEndpointId() == endpointId) + { + return const_cast(&device); + } + } + return nullptr; +} + +Device * DeviceManager::FindDeviceByNode(NodeId nodeId) +{ + for (auto & device : mSyncedDevices) + { + if (device.GetNodeId() == nodeId) + { + return const_cast(&device); + } + } + return nullptr; +} + +void DeviceManager::RemoveSyncedDevice(NodeId nodeId) +{ + Device * device = FindDeviceByNode(nodeId); + if (device == nullptr) + { + ChipLogProgress(NotSpecified, "No device found with NodeId:" ChipLogFormatX64, ChipLogValueX64(nodeId)); + return; + } + + mSyncedDevices.erase(*device); + ChipLogProgress(NotSpecified, "Removed synced device: NodeId:" ChipLogFormatX64 ", EndpointId %u", + ChipLogValueX64(device->GetNodeId()), device->GetEndpointId()); +} + +void DeviceManager::HandleAttributeChange(const app::ConcreteDataAttributePath & path, TLV::TLVReader * data) +{ + if (path.mClusterId != Descriptor::Id || path.mAttributeId != Descriptor::Attributes::PartsList::Id) + { + return; + } + + ChipLogProgress(NotSpecified, "Attribute change detected:"); + ChipLogProgress( + NotSpecified, "Endpoint: %u, Cluster: " ChipLogFormatMEI ", Attribute: " ChipLogFormatMEI ", DataVersion: %" PRIu32, + path.mEndpointId, ChipLogValueMEI(path.mClusterId), ChipLogValueMEI(path.mAttributeId), path.mDataVersion.ValueOr(0)); + + app::DataModel::DecodableList value; + CHIP_ERROR error = app::DataModel::Decode(*data, value); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to decode attribute value. Error: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + + std::set newEndpoints; + + // Populate the newEndpoints set from the decoded value using an iterator + auto iter = value.begin(); + while (iter.Next()) + { + newEndpoints.insert(iter.GetValue()); + } + + if (iter.GetStatus() != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to iterate over decoded attribute value."); + return; + } + + // Compare newEndpoints with mSyncedDevices to determine added and removed endpoints + std::vector addedEndpoints; + std::vector removedEndpoints; + + // Note: We're using vectors and manual searches instead of set operations + // because we need to work with the Device objects in mSyncedDevices, + // not just their EndpointIds. This approach allows us to access the full + // Device information when processing changes. + + // Find added endpoints + for (const auto & endpoint : newEndpoints) + { + if (FindDeviceByEndpoint(endpoint) == nullptr) + { + addedEndpoints.push_back(endpoint); + } + } + + // Find removed endpoints + for (auto & device : mSyncedDevices) + { + EndpointId endpointId = device.GetEndpointId(); + if (newEndpoints.find(endpointId) == newEndpoints.end()) + { + removedEndpoints.push_back(endpointId); + } + } + + // Process added endpoints + for (const auto & endpoint : addedEndpoints) + { + ChipLogProgress(NotSpecified, "Endpoint added: %u", endpoint); + + if (mAutoSyncEnabled) + { + char command[64]; + snprintf(command, sizeof(command), "fabricsync sync-device %d", endpoint); + PushCommand(command); + } + } + + // Process removed endpoints + for (const auto & endpoint : removedEndpoints) + { + ChipLogProgress(NotSpecified, "Endpoint removed: %u", endpoint); + + Device * device = FindDeviceByEndpoint(endpoint); + + if (device == nullptr) + { + ChipLogProgress(NotSpecified, "No device on Endpoint: %u", endpoint); + continue; + } + + if (mAutoSyncEnabled) + { + char command[64]; + snprintf(command, sizeof(command), "pairing unpair %ld", device->GetNodeId()); + + PairingCommand * pairingCommand = static_cast(CommandMgr().GetCommandByName("pairing", "unpair")); + + if (pairingCommand == nullptr) + { + ChipLogError(NotSpecified, "Pairing code command is not available"); + return; + } + + pairingCommand->RegisterPairingDelegate(this); + PushCommand(command); + } + } +} + +void DeviceManager::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) +{ + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to remove synced device:(" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + return; + } + + RemoveSyncedDevice(deviceId); + ChipLogProgress(NotSpecified, "Synced device with NodeId:" ChipLogFormatX64 " has been removed.", ChipLogValueX64(deviceId)); +} diff --git a/examples/fabric-admin/device_manager/DeviceManager.h b/examples/fabric-admin/device_manager/DeviceManager.h new file mode 100644 index 00000000000000..6270cfd40e9df0 --- /dev/null +++ b/examples/fabric-admin/device_manager/DeviceManager.h @@ -0,0 +1,102 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +#include + +class Device +{ +public: + Device(chip::NodeId nodeId, chip::EndpointId endpointId) : mNodeId(nodeId), mEndpointId(endpointId) {} + + chip::NodeId GetNodeId() const { return mNodeId; } + chip::EndpointId GetEndpointId() const { return mEndpointId; } + + bool operator<(const Device & other) const + { + return mNodeId < other.mNodeId || (mNodeId == other.mNodeId && mEndpointId < other.mEndpointId); + } + +private: + chip::NodeId mNodeId; + chip::EndpointId mEndpointId; +}; + +class DeviceManager : public PairingDelegate +{ +public: + DeviceManager() = default; + + void Init(); + + chip::NodeId GetNextAvailableNodeId(); + + chip::NodeId GetRemoteBridgeNodeId() const { return mRemoteBridgeNodeId; } + + void UpdateLastUsedNodeId(chip::NodeId nodeId); + + void SetRemoteBridgeNodeId(chip::NodeId remoteBridgeNodeId) { mRemoteBridgeNodeId = remoteBridgeNodeId; } + + bool IsAutoSyncEnabled() const { return mAutoSyncEnabled; } + + bool IsFabricSyncReady() const { return mRemoteBridgeNodeId != chip::kUndefinedNodeId; } + + void EnableAutoSync(bool state) { mAutoSyncEnabled = state; } + + void AddSyncedDevice(const Device & device); + + void RemoveSyncedDevice(chip::NodeId nodeId); + + void HandleAttributeChange(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data); + + void OnDeviceRemoved(chip::NodeId deviceId, CHIP_ERROR err) override; + +private: + friend DeviceManager & DeviceMgr(); + + static DeviceManager sInstance; + + chip::NodeId mLastUsedNodeId = 0; + chip::NodeId mRemoteBridgeNodeId = chip::kUndefinedNodeId; + std::set mSyncedDevices; + bool mAutoSyncEnabled = false; + bool mInitialized = false; + + Device * FindDeviceByEndpoint(chip::EndpointId endpointId); + Device * FindDeviceByNode(chip::NodeId nodeId); +}; + +/** + * Returns the public interface of the DeviceManager singleton object. + * + * Applications should use this to access features of the DeviceManager + * object. + */ +inline DeviceManager & DeviceMgr() +{ + if (!DeviceManager::sInstance.mInitialized) + { + DeviceManager::sInstance.Init(); + } + return DeviceManager::sInstance; +} diff --git a/examples/fabric-admin/main.cpp b/examples/fabric-admin/main.cpp index d85578f784c293..c7f9089c120c8d 100644 --- a/examples/fabric-admin/main.cpp +++ b/examples/fabric-admin/main.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,8 @@ void ApplicationInit() InitRpcServer(kFabricAdminServerPort); ChipLogProgress(NotSpecified, "PW_RPC initialized."); #endif + + DeviceMgr().Init(); } // ================================================================================ diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index b3cbdcea05409a..51ecb1ff6c13c5 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -20,6 +20,8 @@ #include "pw_rpc_system_server/rpc_server.h" #include "pw_rpc_system_server/socket.h" +#include +#include #include #include @@ -27,17 +29,26 @@ #include "pigweed/rpc_services/FabricAdmin.h" #endif +using namespace ::chip; + namespace { #if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE -class FabricAdmin final : public chip::rpc::FabricAdmin +class FabricAdmin final : public rpc::FabricAdmin { public: pw::Status OpenCommissioningWindow(const chip_rpc_DeviceInfo & request, chip_rpc_OperationStatus & response) override { - chip::NodeId nodeId = request.node_id; + NodeId nodeId = request.node_id; ChipLogProgress(NotSpecified, "Received OpenCommissioningWindow request: 0x%lx", nodeId); - response.success = false; + + char command[64]; + snprintf(command, sizeof(command), "pairing open-commissioning-window %ld %d %d %d %d %d", nodeId, kRootEndpointId, + kEnhancedCommissioningMethod, kWindowTimeout, kIteration, kDiscriminator); + + PushCommand(command); + + response.success = true; return pw::OkStatus(); }