Skip to content

Commit

Permalink
[Fabric-Admin] Implement FabricSyncGetter APIs (project-chip#36108)
Browse files Browse the repository at this point in the history
* [Fabric-Admin] Implement FabricSyncGetter APIs

* Update examples/fabric-admin/device_manager/FabricSyncGetter.h

Co-authored-by: Terence Hampson <[email protected]>

---------

Co-authored-by: Terence Hampson <[email protected]>
  • Loading branch information
yufengwangca and tehampson authored Oct 17, 2024
1 parent d9c6de5 commit c0c674c
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 14 deletions.
2 changes: 2 additions & 0 deletions examples/fabric-admin/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 0 additions & 2 deletions examples/fabric-admin/commands/clusters/ReportCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
22 changes: 10 additions & 12 deletions examples/fabric-admin/device_manager/DeviceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,18 @@ void DeviceManager::ReadSupportedDeviceCategories()
return;
}

StringBuilder<kMaxCommandSize> 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)
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions examples/fabric-admin/device_manager/DeviceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <app-common/zap-generated/cluster-objects.h>
#include <device_manager/BridgeSubscription.h>
#include <device_manager/FabricSyncGetter.h>
#include <device_manager/PairingManager.h>
#include <platform/CHIPDeviceLayer.h>

Expand Down Expand Up @@ -212,6 +213,7 @@ class DeviceManager : public PairingDelegate
uint64_t mRequestId = 0;

BridgeSubscription mBridgeSubscriber;
FabricSyncGetter mFabricSyncGetter;
};

/**
Expand Down
121 changes: 121 additions & 0 deletions examples/fabric-admin/device_manager/FabricSyncGetter.cpp
Original file line number Diff line number Diff line change
@@ -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<FabricSyncGetter *>(context)->OnDeviceConnected(exchangeMgr, sessionHandle);
}

void OnDeviceConnectionFailureWrapper(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
{
reinterpret_cast<FabricSyncGetter *>(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<ReadClient>(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);
}
75 changes: 75 additions & 0 deletions examples/fabric-admin/device_manager/FabricSyncGetter.h
Original file line number Diff line number Diff line change
@@ -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 <app/ReadClient.h>
#include <controller/CHIPDeviceController.h>

#include <memory>
#include <optional>

/**
* @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<void(chip::TLV::TLVReader & data)>;

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<chip::app::ReadClient> mClient;

OnDoneCallback mOnDoneCallback;
chip::EndpointId mEndpointId;
chip::Callback::Callback<chip::OnDeviceConnected> mOnDeviceConnectedCallback;
chip::Callback::Callback<chip::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
};

0 comments on commit c0c674c

Please sign in to comment.