From c0c674c56fe13af0552ff8aed28deac3699e4535 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 17 Oct 2024 12:34:16 -0700 Subject: [PATCH] [Fabric-Admin] Implement FabricSyncGetter APIs (#36108) * [Fabric-Admin] Implement FabricSyncGetter APIs * Update examples/fabric-admin/device_manager/FabricSyncGetter.h Co-authored-by: Terence Hampson --------- Co-authored-by: Terence Hampson --- examples/fabric-admin/BUILD.gn | 2 + .../commands/clusters/ReportCommand.cpp | 2 - .../device_manager/DeviceManager.cpp | 22 ++-- .../device_manager/DeviceManager.h | 2 + .../device_manager/FabricSyncGetter.cpp | 121 ++++++++++++++++++ .../device_manager/FabricSyncGetter.h | 75 +++++++++++ 6 files changed, 210 insertions(+), 14 deletions(-) create mode 100644 examples/fabric-admin/device_manager/FabricSyncGetter.cpp create mode 100644 examples/fabric-admin/device_manager/FabricSyncGetter.h diff --git a/examples/fabric-admin/BUILD.gn b/examples/fabric-admin/BUILD.gn index 38252cd30e7648..58d9cee914e410 100644 --- a/examples/fabric-admin/BUILD.gn +++ b/examples/fabric-admin/BUILD.gn @@ -90,6 +90,8 @@ static_library("fabric-admin-utils") { "device_manager/DeviceSubscriptionManager.h", "device_manager/DeviceSynchronization.cpp", "device_manager/DeviceSynchronization.h", + "device_manager/FabricSyncGetter.cpp", + "device_manager/FabricSyncGetter.h", "device_manager/PairingManager.cpp", "device_manager/PairingManager.h", "device_manager/UniqueIdGetter.cpp", diff --git a/examples/fabric-admin/commands/clusters/ReportCommand.cpp b/examples/fabric-admin/commands/clusters/ReportCommand.cpp index df6f329896036c..7f3decd78a83f0 100644 --- a/examples/fabric-admin/commands/clusters/ReportCommand.cpp +++ b/examples/fabric-admin/commands/clusters/ReportCommand.cpp @@ -45,8 +45,6 @@ void ReportCommand::OnAttributeData(const app::ConcreteDataAttributePath & path, } LogErrorOnFailure(RemoteDataModelLogger::LogAttributeAsJSON(path, data)); - - DeviceMgr().HandleAttributeData(path, *data); } void ReportCommand::OnEventData(const app::EventHeader & eventHeader, TLV::TLVReader * data, const app::StatusIB * status) diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index 2968bcf001e9bc..3bfd677d962435 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -212,13 +212,18 @@ void DeviceManager::ReadSupportedDeviceCategories() return; } - StringBuilder commandBuilder; + ChipLogProgress(NotSpecified, "Read SupportedDeviceCategories from the remote bridge."); - commandBuilder.Add("commissionercontrol read supported-device-categories "); - commandBuilder.AddFormat("%ld ", mRemoteBridgeNodeId); - commandBuilder.AddFormat("%d", kAggregatorEndpointId); + CHIP_ERROR error = mFabricSyncGetter.GetFabricSynchronizationData( + [this](TLV::TLVReader & data) { this->HandleReadSupportedDeviceCategories(data); }, + PairingManager::Instance().CurrentCommissioner(), this->GetRemoteBridgeNodeId(), kAggregatorEndpointId); - PushCommand(commandBuilder.c_str()); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, + "Failed to read SupportedDeviceCategories from the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, + mRemoteBridgeNodeId, error.Format()); + } } void DeviceManager::HandleReadSupportedDeviceCategories(TLV::TLVReader & data) @@ -421,13 +426,6 @@ void DeviceManager::HandleReverseOpenCommissioningWindow(TLV::TLVReader & data) void DeviceManager::HandleAttributeData(const app::ConcreteDataAttributePath & path, TLV::TLVReader & data) { - if (path.mClusterId == CommissionerControl::Id && - path.mAttributeId == CommissionerControl::Attributes::SupportedDeviceCategories::Id) - { - HandleReadSupportedDeviceCategories(data); - return; - } - if (path.mClusterId == Descriptor::Id && path.mAttributeId == Descriptor::Attributes::PartsList::Id) { HandleAttributePartsListUpdate(data); diff --git a/examples/fabric-admin/device_manager/DeviceManager.h b/examples/fabric-admin/device_manager/DeviceManager.h index 62d5ae045bb6af..43461f41c17229 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.h +++ b/examples/fabric-admin/device_manager/DeviceManager.h @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -212,6 +213,7 @@ class DeviceManager : public PairingDelegate uint64_t mRequestId = 0; BridgeSubscription mBridgeSubscriber; + FabricSyncGetter mFabricSyncGetter; }; /** diff --git a/examples/fabric-admin/device_manager/FabricSyncGetter.cpp b/examples/fabric-admin/device_manager/FabricSyncGetter.cpp new file mode 100644 index 00000000000000..5201048c3faea6 --- /dev/null +++ b/examples/fabric-admin/device_manager/FabricSyncGetter.cpp @@ -0,0 +1,121 @@ +/* + * 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 "FabricSyncGetter.h" + +using namespace ::chip; +using namespace ::chip::app; +using chip::app::ReadClient; + +namespace { + +void OnDeviceConnectedWrapper(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + reinterpret_cast(context)->OnDeviceConnected(exchangeMgr, sessionHandle); +} + +void OnDeviceConnectionFailureWrapper(void * context, const ScopedNodeId & peerId, CHIP_ERROR error) +{ + reinterpret_cast(context)->OnDeviceConnectionFailure(peerId, error); +} + +} // namespace + +FabricSyncGetter::FabricSyncGetter() : + mOnDeviceConnectedCallback(OnDeviceConnectedWrapper, this), + mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureWrapper, this) +{} + +CHIP_ERROR FabricSyncGetter::GetFabricSynchronizationData(OnDoneCallback onDoneCallback, Controller::DeviceController & controller, + NodeId nodeId, EndpointId endpointId) +{ + assertChipStackLockedByCurrentThread(); + + mEndpointId = endpointId; + mOnDoneCallback = onDoneCallback; + + CHIP_ERROR err = controller.GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to connect to remote fabric bridge %" CHIP_ERROR_FORMAT, err.Format()); + } + return err; +} + +void FabricSyncGetter::OnAttributeData(const ConcreteDataAttributePath & path, TLV::TLVReader * data, const StatusIB & status) +{ + VerifyOrDie(path.mClusterId == Clusters::CommissionerControl::Id); + + if (!status.IsSuccess()) + { + ChipLogError(NotSpecified, "Response Failure: %" CHIP_ERROR_FORMAT, status.ToChipError().Format()); + return; + } + + switch (path.mAttributeId) + { + case Clusters::CommissionerControl::Attributes::SupportedDeviceCategories::Id: { + mOnDoneCallback(*data); + break; + } + default: + break; + } +} + +void FabricSyncGetter::OnError(CHIP_ERROR error) +{ + ChipLogProgress(NotSpecified, "Error Getting SupportedDeviceCategories: %" CHIP_ERROR_FORMAT, error.Format()); +} + +void FabricSyncGetter::OnDone(ReadClient * apReadClient) +{ + ChipLogProgress(NotSpecified, "Reading SupportedDeviceCategories is done."); +} + +void FabricSyncGetter::OnDeviceConnected(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + mClient = std::make_unique(app::InteractionModelEngine::GetInstance(), &exchangeMgr, *this /* callback */, + ReadClient::InteractionType::Read); + VerifyOrDie(mClient); + + AttributePathParams readPaths[1]; + readPaths[0] = AttributePathParams(mEndpointId, Clusters::CommissionerControl::Id, + Clusters::CommissionerControl::Attributes::SupportedDeviceCategories::Id); + + ReadPrepareParams readParams(sessionHandle); + + readParams.mpAttributePathParamsList = readPaths; + readParams.mAttributePathParamsListSize = 1; + + CHIP_ERROR err = mClient->SendRequest(readParams); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to read SupportedDeviceCategories from the bridged device."); + OnDone(nullptr); + return; + } +} + +void FabricSyncGetter::OnDeviceConnectionFailure(const ScopedNodeId & peerId, CHIP_ERROR error) +{ + ChipLogError(NotSpecified, "FabricSyncGetter failed to connect to " ChipLogFormatX64, ChipLogValueX64(peerId.GetNodeId())); + + OnDone(nullptr); +} diff --git a/examples/fabric-admin/device_manager/FabricSyncGetter.h b/examples/fabric-admin/device_manager/FabricSyncGetter.h new file mode 100644 index 00000000000000..d6d3a5bce8c9f5 --- /dev/null +++ b/examples/fabric-admin/device_manager/FabricSyncGetter.h @@ -0,0 +1,75 @@ +/* + * 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 + +/** + * @brief Class used to get FabricSynchronization from SupportedDeviceCategories attribute of Commissioner Control Cluster. + * + * Functionality: + * - Establishes a CASE session to communicate with the remote bridge. + * - Retrieves the attribute data from the endpoint which host Aggregator. + * - Provides callbacks for success, error, and completion when retrieving data. + */ +class FabricSyncGetter : public chip::app::ReadClient::Callback +{ +public: + using OnDoneCallback = std::function; + + FabricSyncGetter(); + + /** + * @brief Initiates the process of retrieving fabric synchronization data from the target device. + * + * @param onDoneCallback A callback function to be invoked when the data retrieval is complete. + * @param controller The device controller used to establish a session with the target device. + * @param nodeId The Node ID of the target device. + * @param endpointId The Endpoint ID from which to retrieve the fabric synchronization data. + * @return CHIP_ERROR Returns an error if the process fails, CHIP_NO_ERROR on success. + */ + CHIP_ERROR GetFabricSynchronizationData(OnDoneCallback onDoneCallback, chip::Controller::DeviceController & controller, + chip::NodeId nodeId, chip::EndpointId endpointId); + + /////////////////////////////////////////////////////////////// + // ReadClient::Callback implementation + /////////////////////////////////////////////////////////////// + void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data, + const chip::app::StatusIB & status) override; + void OnError(CHIP_ERROR error) override; + void OnDone(chip::app::ReadClient * apReadClient) override; + + /////////////////////////////////////////////////////////////// + // callbacks for CASE session establishment + /////////////////////////////////////////////////////////////// + void OnDeviceConnected(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); + void OnDeviceConnectionFailure(const chip::ScopedNodeId & peerId, CHIP_ERROR error); + +private: + std::unique_ptr mClient; + + OnDoneCallback mOnDoneCallback; + chip::EndpointId mEndpointId; + chip::Callback::Callback mOnDeviceConnectedCallback; + chip::Callback::Callback mOnDeviceConnectionFailureCallback; +};