Skip to content

Commit

Permalink
Merge branch 'master' into feature/add_brd4343a_support
Browse files Browse the repository at this point in the history
  • Loading branch information
arun-silabs authored Oct 17, 2024
2 parents 08e88e1 + 150db87 commit 618a311
Show file tree
Hide file tree
Showing 38 changed files with 625 additions and 6,607 deletions.
22 changes: 6 additions & 16 deletions .github/workflows/stale.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,17 @@ jobs:
with:
stale-issue-message:
"This issue has been automatically marked as stale because
it has not had recent activity. It will be closed if no
further activity occurs. Remove stale label or comment or
this will be closed in 30 days."
it has not had recent activity."
stale-pr-message:
"This pull request has been automatically marked as stale
because it has not had recent activity. It will be closed
if no further activity occurs. Remove stale label or
comment or this will be closed in 10 days."
because it has not had recent activity."
close-issue-message:
"This stale issue has been automatically closed. Thank you
for your contributions."
close-pr-message:
"This stale pull request has been automatically closed.
Thank you for your contributions."
days-before-issue-stale: 30
days-before-issue-close: -1 # Don't close them for now
days-before-pr-stale: 90
days-before-pr-close: 10
exempt-issue-labels:
"security,blocked,cert blocker,build issue,Spec XML
align,CI/CD improvements,memory"
exempt-pr-labels:
"security,blocked,cert blocker,build issue,Spec XML
align,CI/CD improvements,memory"
days-before-issue-stale: 180
days-before-issue-close: -1 # Don't close stale issues
days-before-pr-stale: 180
days-before-pr-close: -1 # Don't close stale PRs
2 changes: 2 additions & 0 deletions examples/fabric-admin/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ static_library("fabric-admin-utils") {
"commands/pairing/OpenCommissioningWindowCommand.h",
"commands/pairing/PairingCommand.cpp",
"commands/pairing/ToTLVCert.cpp",
"device_manager/BridgeSubscription.cpp",
"device_manager/BridgeSubscription.h",
"device_manager/DeviceManager.cpp",
"device_manager/DeviceManager.h",
"device_manager/DeviceSubscription.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 @@ -72,6 +72,4 @@ void ReportCommand::OnEventData(const app::EventHeader & eventHeader, TLV::TLVRe
}

LogErrorOnFailure(RemoteDataModelLogger::LogEventAsJSON(eventHeader, data));

DeviceMgr().HandleEventData(eventHeader, *data);
}
159 changes: 159 additions & 0 deletions examples/fabric-admin/device_manager/BridgeSubscription.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* 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 "BridgeSubscription.h"
#include <device_manager/DeviceManager.h>

using namespace ::chip;
using namespace ::chip::app;
using chip::app::ReadClient;

namespace {

constexpr uint16_t kSubscribeMinInterval = 0;
constexpr uint16_t kSubscribeMaxInterval = 60;

void OnDeviceConnectedWrapper(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle)
{
reinterpret_cast<BridgeSubscription *>(context)->OnDeviceConnected(exchangeMgr, sessionHandle);
}

void OnDeviceConnectionFailureWrapper(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
{
reinterpret_cast<BridgeSubscription *>(context)->OnDeviceConnectionFailure(peerId, error);
}

} // namespace

BridgeSubscription::BridgeSubscription() :
mOnDeviceConnectedCallback(OnDeviceConnectedWrapper, this),
mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureWrapper, this)
{}

CHIP_ERROR BridgeSubscription::StartSubscription(Controller::DeviceController & controller, NodeId nodeId, EndpointId endpointId)
{
assertChipStackLockedByCurrentThread();

VerifyOrDie(!subscriptionStarted); // Ensure it's not called multiple times.

// Mark as started
subscriptionStarted = true;

mEndpointId = endpointId;

CHIP_ERROR err = controller.GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback);
if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "Failed to connect to remote fabric sync bridge %" CHIP_ERROR_FORMAT, err.Format());
}
return err;
}

void BridgeSubscription::OnAttributeData(const ConcreteDataAttributePath & path, TLV::TLVReader * data, const StatusIB & status)
{
if (!status.IsSuccess())
{
ChipLogError(NotSpecified, "Response Failure: %" CHIP_ERROR_FORMAT, status.ToChipError().Format());
return;
}

if (data == nullptr)
{
ChipLogError(NotSpecified, "Response Failure: No Data");
return;
}

DeviceMgr().HandleAttributeData(path, *data);
}

void BridgeSubscription::OnEventData(const app::EventHeader & eventHeader, TLV::TLVReader * data, const app::StatusIB * status)
{
if (status != nullptr)
{
CHIP_ERROR error = status->ToChipError();
if (CHIP_NO_ERROR != error)
{
ChipLogError(NotSpecified, "Response Failure: %" CHIP_ERROR_FORMAT, error.Format());
return;
}
}

if (data == nullptr)
{
ChipLogError(NotSpecified, "Response Failure: No Data");
return;
}

DeviceMgr().HandleEventData(eventHeader, *data);
}

void BridgeSubscription::OnError(CHIP_ERROR error)
{
ChipLogProgress(NotSpecified, "Error on remote fabric sync bridge subscription: %" CHIP_ERROR_FORMAT, error.Format());
}

void BridgeSubscription::OnDone(ReadClient * apReadClient)
{
mClient.reset();
ChipLogProgress(NotSpecified, "The remote fabric sync bridge subscription is terminated");

// Reset the subscription state to allow retry
subscriptionStarted = false;

// TODO:(#36092) Fabric-Admin should attempt to re-subscribe when the subscription to the remote bridge is terminated.
}

void BridgeSubscription::OnDeviceConnected(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle)
{
mClient = std::make_unique<ReadClient>(app::InteractionModelEngine::GetInstance(), &exchangeMgr /* echangeMgr */,
*this /* callback */, ReadClient::InteractionType::Subscribe);
VerifyOrDie(mClient);

AttributePathParams readPaths[1];
readPaths[0] = AttributePathParams(mEndpointId, Clusters::Descriptor::Id, Clusters::Descriptor::Attributes::PartsList::Id);

EventPathParams eventPaths[1];
eventPaths[0] = EventPathParams(mEndpointId, Clusters::CommissionerControl::Id,
Clusters::CommissionerControl::Events::CommissioningRequestResult::Id);
eventPaths[0].mIsUrgentEvent = true;

ReadPrepareParams readParams(sessionHandle);

readParams.mpAttributePathParamsList = readPaths;
readParams.mAttributePathParamsListSize = 1;
readParams.mpEventPathParamsList = eventPaths;
readParams.mEventPathParamsListSize = 1;
readParams.mMinIntervalFloorSeconds = kSubscribeMinInterval;
readParams.mMaxIntervalCeilingSeconds = kSubscribeMaxInterval;
readParams.mKeepSubscriptions = true;

CHIP_ERROR err = mClient->SendRequest(readParams);

if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "Failed to issue subscription to the Descriptor Cluster of the remote bridged device.");
OnDone(nullptr);
return;
}
}

void BridgeSubscription::OnDeviceConnectionFailure(const ScopedNodeId & peerId, CHIP_ERROR error)
{
ChipLogError(NotSpecified, "BridgeSubscription failed to connect to " ChipLogFormatX64, ChipLogValueX64(peerId.GetNodeId()));
OnDone(nullptr);
}
77 changes: 77 additions & 0 deletions examples/fabric-admin/device_manager/BridgeSubscription.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* 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 subscribe to attributes and events from the remote bridged device.
*
* The Descriptor Cluster contains attributes such as the Parts List, which provides a list
* of endpoints or devices that are part of a composite device or bridge. The CommissionerControl
* Cluster generates events related to commissioning requests, which can be monitored to track
* device commissioning status.
*
* When subscribing to attributes and events of a bridged device from another fabric, the class:
* - Establishes a secure session with the device (if needed) via CASE (Chip over
* Authenticated Session Establishment) session.
* - Subscribes to the specified attributes in the Descriptor Cluster (e.g., Parts List) and
* events in the CommissionerControl Cluster (e.g., CommissioningRequestResult) of the remote
* device on the specified node and endpoint.
* - Invokes the provided callback upon successful or unsuccessful subscription, allowing
* further handling of data or errors.
*
* This class also implements the necessary callbacks to handle attribute data reports, event data,
* errors, and session establishment procedures.
*/
class BridgeSubscription : public chip::app::ReadClient::Callback
{
public:
BridgeSubscription();

CHIP_ERROR StartSubscription(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 OnEventData(const chip::app::EventHeader & eventHeader, 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;

chip::Callback::Callback<chip::OnDeviceConnected> mOnDeviceConnectedCallback;
chip::Callback::Callback<chip::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
chip::EndpointId mEndpointId;
bool subscriptionStarted = false;
};
27 changes: 9 additions & 18 deletions examples/fabric-admin/device_manager/DeviceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ namespace {
constexpr EndpointId kAggregatorEndpointId = 1;
constexpr uint16_t kWindowTimeout = 300;
constexpr uint16_t kIteration = 1000;
constexpr uint16_t kSubscribeMinInterval = 0;
constexpr uint16_t kSubscribeMaxInterval = 60;
constexpr uint16_t kAggragatorEndpointId = 1;
constexpr uint16_t kMaxDiscriminatorLength = 4095;

} // namespace
Expand Down Expand Up @@ -193,23 +190,17 @@ void DeviceManager::UnpairLocalFabricBridge()

void DeviceManager::SubscribeRemoteFabricBridge()
{
// Listen to the state changes of the remote fabric bridge.
StringBuilder<kMaxCommandSize> commandBuilder;

// Prepare and push the descriptor subscribe command
commandBuilder.Add("descriptor subscribe parts-list ");
commandBuilder.AddFormat("%d %d %lu %d", kSubscribeMinInterval, kSubscribeMaxInterval, mRemoteBridgeNodeId,
kAggragatorEndpointId);
PushCommand(commandBuilder.c_str());
ChipLogProgress(NotSpecified, "Start subscription to the remote bridge.")

// Clear the builder for the next command
commandBuilder.Reset();
CHIP_ERROR error = mBridgeSubscriber.StartSubscription(PairingManager::Instance().CurrentCommissioner(),
mRemoteBridgeNodeId, kAggregatorEndpointId);

// Prepare and push the commissioner control subscribe command
commandBuilder.Add("commissionercontrol subscribe-event commissioning-request-result ");
commandBuilder.AddFormat("%d %d %lu %d --is-urgent true --keepSubscriptions true", kSubscribeMinInterval, kSubscribeMaxInterval,
mRemoteBridgeNodeId, kAggregatorEndpointId);
PushCommand(commandBuilder.c_str());
if (error != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "Failed to subscribe to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT,
mRemoteBridgeNodeId, error.Format());
return;
}
}

void DeviceManager::ReadSupportedDeviceCategories()
Expand Down
3 changes: 3 additions & 0 deletions examples/fabric-admin/device_manager/DeviceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#pragma once

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

Expand Down Expand Up @@ -209,6 +210,8 @@ class DeviceManager : public PairingDelegate
bool mAutoSyncEnabled = false;
bool mInitialized = false;
uint64_t mRequestId = 0;

BridgeSubscription mBridgeSubscriber;
};

/**
Expand Down
Loading

0 comments on commit 618a311

Please sign in to comment.