Skip to content

Commit 068da61

Browse files
authored
Add plumbing that allows fabric-bridge endpoints to report CADMIN attr (#35076)
1 parent 56ed10a commit 068da61

File tree

5 files changed

+156
-0
lines changed

5 files changed

+156
-0
lines changed

examples/fabric-bridge-app/fabric-bridge-common/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ source_set("fabric-bridge-lib") {
4141
public_configs = [ ":config" ]
4242

4343
sources = [
44+
"include/BridgedAdministratorCommissioning.h",
4445
"include/BridgedDevice.h",
4546
"include/BridgedDeviceBasicInformationImpl.h",
4647
"include/BridgedDeviceManager.h",
4748
"include/CHIPProjectAppConfig.h",
49+
"src/BridgedAdministratorCommissioning.cpp",
4850
"src/BridgedDevice.cpp",
4951
"src/BridgedDeviceBasicInformationImpl.cpp",
5052
"src/BridgedDeviceManager.cpp",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2024 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#pragma once
19+
20+
#include <app-common/zap-generated/cluster-objects.h>
21+
#include <app/AttributeAccessInterfaceRegistry.h>
22+
23+
/**
24+
* @brief CADMIN cluster implementation for handling attribute interactions of bridged device endpoints.
25+
*
26+
* The current Administrator Commissioning Cluster server's zap generated code will automatically
27+
* register an Attribute Access Interface for the root node endpoint implementation. In order to
28+
* properly respond to a read attribute for bridged devices we are representing, we override the
29+
* currently registered Attribute Interface such that we are first to receive any read attribute
30+
* request on Administrator Commissioning Cluster, and if it is not an endpoint for a device we
31+
* are a bridge for we redirect to the default cluster server implementation of Administrator
32+
* Commissioning Cluster.
33+
*/
34+
class BridgedAdministratorCommissioning : public chip::app::AttributeAccessInterface
35+
{
36+
public:
37+
// Register for the AdministratorCommissioning cluster on all endpoints.
38+
BridgedAdministratorCommissioning() :
39+
AttributeAccessInterface(chip::NullOptional, chip::app::Clusters::AdministratorCommissioning::Id)
40+
{}
41+
42+
CHIP_ERROR Init();
43+
44+
CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override;
45+
46+
// We do not allow writing to CADMIN attributes of a bridged device endpoint. We simply redirect
47+
// write requests to the original attribute interface.
48+
CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override
49+
{
50+
VerifyOrDie(mOriginalAttributeInterface);
51+
return mOriginalAttributeInterface->Write(aPath, aDecoder);
52+
}
53+
54+
private:
55+
// If mOriginalAttributeInterface is removed from here, the class description needs to be updated
56+
// to reflect this change.
57+
chip::app::AttributeAccessInterface * mOriginalAttributeInterface = nullptr;
58+
};

examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDevice.h

+12
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#pragma once
2020

21+
#include <app-common/zap-generated/cluster-objects.h>
2122
#include <app/util/attribute-storage.h>
2223

2324
#include <string>
@@ -40,6 +41,14 @@ class BridgedDevice
4041
std::string softwareVersionString;
4142
};
4243

44+
struct AdminCommissioningAttributes
45+
{
46+
chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum commissioningWindowStatus =
47+
chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen;
48+
std::optional<chip::FabricIndex> openerFabricIndex = std::nullopt;
49+
std::optional<chip::VendorId> openerVendorId = std::nullopt;
50+
};
51+
4352
BridgedDevice(chip::NodeId nodeId);
4453
virtual ~BridgedDevice() = default;
4554

@@ -59,6 +68,8 @@ class BridgedDevice
5968

6069
[[nodiscard]] const BridgedAttributes & GetBridgedAttributes() const { return mAttributes; }
6170
void SetBridgedAttributes(const BridgedAttributes & value) { mAttributes = value; }
71+
// TODO(#35077): Need to allow mAdminCommissioningAttributes to be set from fabric-admin.
72+
const AdminCommissioningAttributes & GetAdminCommissioningAttributes() const { return mAdminCommissioningAttributes; }
6273

6374
/// Convenience method to set just the unique id of a bridged device as it
6475
/// is one of the few attributes that is not always bulk-set
@@ -73,4 +84,5 @@ class BridgedDevice
7384
chip::EndpointId mParentEndpointId = 0;
7485

7586
BridgedAttributes mAttributes;
87+
AdminCommissioningAttributes mAdminCommissioningAttributes;
7688
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright (c) 2024 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "BridgedAdministratorCommissioning.h"
19+
20+
#include "BridgedDevice.h"
21+
#include "BridgedDeviceManager.h"
22+
#include <app/AttributeAccessInterfaceRegistry.h>
23+
24+
using namespace chip;
25+
using namespace chip::app;
26+
using namespace chip::app::Clusters;
27+
using namespace chip::app::Clusters::AdministratorCommissioning;
28+
29+
CHIP_ERROR BridgedAdministratorCommissioning::Init()
30+
{
31+
// We expect initialization after all embr plugin clusters initialization. This allows us to unregister
32+
// the existing AccessAttributeInterface for AdministratorCommissioning and register ourselves, ensuring
33+
// we get the callback for reading attribute. If the read is not intended for a bridged device we will
34+
// forward it to the original attribute interface that we are unregistering.
35+
mOriginalAttributeInterface = AttributeAccessInterfaceRegistry::Instance().Get(kRootEndpointId, AdministratorCommissioning::Id);
36+
VerifyOrReturnError(mOriginalAttributeInterface, CHIP_ERROR_INTERNAL);
37+
AttributeAccessInterfaceRegistry::Instance().Unregister(mOriginalAttributeInterface);
38+
VerifyOrDie(AttributeAccessInterfaceRegistry::Instance().Register(this));
39+
return CHIP_NO_ERROR;
40+
}
41+
42+
CHIP_ERROR BridgedAdministratorCommissioning::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
43+
{
44+
VerifyOrDie(aPath.mClusterId == Clusters::AdministratorCommissioning::Id);
45+
EndpointId endpointId = aPath.mEndpointId;
46+
BridgedDevice * device = BridgeDeviceMgr().GetDevice(endpointId);
47+
48+
if (!device)
49+
{
50+
VerifyOrDie(mOriginalAttributeInterface);
51+
return mOriginalAttributeInterface->Read(aPath, aEncoder);
52+
}
53+
auto attr = device->GetAdminCommissioningAttributes();
54+
55+
switch (aPath.mAttributeId)
56+
{
57+
case Attributes::WindowStatus::Id: {
58+
return aEncoder.Encode(attr.commissioningWindowStatus);
59+
}
60+
case Attributes::AdminFabricIndex::Id: {
61+
DataModel::Nullable<FabricIndex> encodeableFabricIndex = DataModel::NullNullable;
62+
if (attr.openerFabricIndex.has_value())
63+
{
64+
encodeableFabricIndex.SetNonNull(attr.openerFabricIndex.value());
65+
}
66+
return aEncoder.Encode(encodeableFabricIndex);
67+
}
68+
case Attributes::AdminVendorId::Id: {
69+
DataModel::Nullable<VendorId> encodeableVendorId = DataModel::NullNullable;
70+
if (attr.openerVendorId.has_value())
71+
{
72+
encodeableVendorId.SetNonNull(attr.openerVendorId.value());
73+
}
74+
return aEncoder.Encode(encodeableVendorId);
75+
}
76+
default:
77+
break;
78+
}
79+
80+
return CHIP_NO_ERROR;
81+
}

examples/fabric-bridge-app/linux/main.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <AppMain.h>
2020

21+
#include "BridgedAdministratorCommissioning.h"
2122
#include "BridgedDevice.h"
2223
#include "BridgedDeviceBasicInformationImpl.h"
2324
#include "BridgedDeviceManager.h"
@@ -234,6 +235,7 @@ void BridgedDeviceInformationCommandHandler::InvokeCommand(HandlerContext & hand
234235
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
235236
}
236237

238+
BridgedAdministratorCommissioning gBridgedAdministratorCommissioning;
237239
AdministratorCommissioningCommandHandler gAdministratorCommissioningCommandHandler;
238240
BridgedDeviceInformationCommandHandler gBridgedDeviceInformationCommandHandler;
239241

@@ -258,6 +260,7 @@ void ApplicationInit()
258260
pollingThread.detach();
259261

260262
BridgeDeviceMgr().Init();
263+
VerifyOrDie(gBridgedAdministratorCommissioning.Init() == CHIP_NO_ERROR);
261264

262265
VerifyOrDieWithMsg(CommissionerControlInit() == CHIP_NO_ERROR, NotSpecified,
263266
"Failed to initialize Commissioner Control Server");

0 commit comments

Comments
 (0)