Skip to content

Commit

Permalink
Plumbing for CADMIN attribute updates from fabric-admin to fabric-bri…
Browse files Browse the repository at this point in the history
  • Loading branch information
tehampson authored Aug 28, 2024
1 parent 3a568db commit 6b5a2ce
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 1 deletion.
8 changes: 8 additions & 0 deletions examples/common/pigweed/protos/fabric_bridge_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@ message KeepActiveChanged {
uint32 promised_active_duration_ms = 2;
}

message AdministratorCommissioningChanged {
uint64 node_id = 1;
uint32 window_status = 2;
optional uint32 opener_fabric_index = 3;
optional uint32 opener_vendor_id = 4;
}

service FabricBridge {
rpc AddSynchronizedDevice(SynchronizedDevice) returns (pw.protobuf.Empty){}
rpc RemoveSynchronizedDevice(SynchronizedDevice) returns (pw.protobuf.Empty){}
rpc ActiveChanged(KeepActiveChanged) returns (pw.protobuf.Empty){}
rpc AdminCommissioningAttributeChanged(AdministratorCommissioningChanged) returns (pw.protobuf.Empty){}
}
6 changes: 6 additions & 0 deletions examples/common/pigweed/rpc_services/FabricBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ class FabricBridge : public pw_rpc::nanopb::FabricBridge::Service<FabricBridge>
{
return pw::Status::Unimplemented();
}

virtual pw::Status AdminCommissioningAttributeChanged(const chip_rpc_AdministratorCommissioningChanged & request,
pw_protobuf_Empty & response)
{
return pw::Status::Unimplemented();
}
};

} // namespace rpc
Expand Down
17 changes: 17 additions & 0 deletions examples/fabric-admin/rpc/RpcClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,20 @@ CHIP_ERROR ActiveChanged(chip::NodeId nodeId, uint32_t promisedActiveDurationMs)

return WaitForResponse(call);
}

CHIP_ERROR AdminCommissioningAttributeChanged(const chip_rpc_AdministratorCommissioningChanged & data)
{
ChipLogProgress(NotSpecified, "AdminCommissioningAttributeChanged");

// The RPC call is kept alive until it completes. When a response is received, it will be logged by the handler
// function and the call will complete.
auto call = fabricBridgeClient.AdminCommissioningAttributeChanged(data, RpcCompletedWithEmptyResponse);

if (!call.active())
{
// The RPC call was not sent. This could occur due to, for example, an invalid channel ID. Handle if necessary.
return CHIP_ERROR_INTERNAL;
}

return WaitForResponse(call);
}
11 changes: 11 additions & 0 deletions examples/fabric-admin/rpc/RpcClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,14 @@ CHIP_ERROR RemoveSynchronizedDevice(chip::NodeId nodeId);
* - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call.
*/
CHIP_ERROR ActiveChanged(chip::NodeId nodeId, uint32_t promisedActiveDurationMs);

/**
* @brief CADMIN attribute has changed of one of the bridged devices that was previously added.
*
* @param data information regarding change in AdministratorCommissioning attributes
* @return CHIP_ERROR An error code indicating the success or failure of the operation.
* - CHIP_NO_ERROR: The RPC command was successfully processed.
* - CHIP_ERROR_BUSY: Another operation is currently in progress.
* - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call.
*/
CHIP_ERROR AdminCommissioningAttributeChanged(const chip_rpc_AdministratorCommissioningChanged & data);
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class BridgedDevice

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

void SetAdminCommissioningAttributes(const AdminCommissioningAttributes & aAdminCommissioningAttributes);
const AdminCommissioningAttributes & GetAdminCommissioningAttributes() const { return mAdminCommissioningAttributes; }

/// Convenience method to set just the unique id of a bridged device as it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <cstdio>

#include <app/EventLogging.h>
#include <app/reporting/reporting.h>
#include <platform/CHIPDeviceLayer.h>

namespace {
Expand All @@ -31,6 +32,14 @@ struct ActiveChangeEventWorkData
uint32_t mPromisedActiveDuration;
};

struct ReportAttributeChangedWorkData
{
chip::EndpointId mEndpointId;
bool mWindowChanged = false;
bool mFabricIndexChanged = false;
bool mVendorChanged = false;
};

void ActiveChangeEventWork(intptr_t arg)
{
ActiveChangeEventWorkData * data = reinterpret_cast<ActiveChangeEventWorkData *>(arg);
Expand All @@ -47,6 +56,28 @@ void ActiveChangeEventWork(intptr_t arg)
chip::Platform::Delete(data);
}

void ReportAttributeChangedWork(intptr_t arg)
{
ReportAttributeChangedWorkData * data = reinterpret_cast<ReportAttributeChangedWorkData *>(arg);

if (data->mWindowChanged)
{
MatterReportingAttributeChangeCallback(data->mEndpointId, chip::app::Clusters::AdministratorCommissioning::Id,
chip::app::Clusters::AdministratorCommissioning::Attributes::WindowStatus::Id);
}
if (data->mFabricIndexChanged)
{
MatterReportingAttributeChangeCallback(data->mEndpointId, chip::app::Clusters::AdministratorCommissioning::Id,
chip::app::Clusters::AdministratorCommissioning::Attributes::AdminFabricIndex::Id);
}
if (data->mVendorChanged)
{
MatterReportingAttributeChangeCallback(data->mEndpointId, chip::app::Clusters::AdministratorCommissioning::Id,
chip::app::Clusters::AdministratorCommissioning::Attributes::AdminVendorId::Id);
}
chip::Platform::Delete(data);
}

} // namespace

using namespace chip::app::Clusters::Actions;
Expand Down Expand Up @@ -80,3 +111,18 @@ void BridgedDevice::SetReachable(bool reachable)
ChipLogProgress(NotSpecified, "BridgedDevice[%s]: OFFLINE", mAttributes.uniqueId.c_str());
}
}

void BridgedDevice::SetAdminCommissioningAttributes(const AdminCommissioningAttributes & aAdminCommissioningAttributes)
{
ReportAttributeChangedWorkData * workdata = chip::Platform::New<ReportAttributeChangedWorkData>();

workdata->mEndpointId = mEndpointId;
workdata->mWindowChanged =
(aAdminCommissioningAttributes.commissioningWindowStatus != mAdminCommissioningAttributes.commissioningWindowStatus);
workdata->mFabricIndexChanged =
(aAdminCommissioningAttributes.openerFabricIndex != mAdminCommissioningAttributes.openerFabricIndex);
workdata->mVendorChanged = (aAdminCommissioningAttributes.openerVendorId != mAdminCommissioningAttributes.openerVendorId);

mAdminCommissioningAttributes = aAdminCommissioningAttributes;
chip::DeviceLayer::PlatformMgr().ScheduleWork(ReportAttributeChangedWork, reinterpret_cast<intptr_t>(workdata));
}
40 changes: 40 additions & 0 deletions examples/fabric-bridge-app/linux/RpcServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class FabricBridge final : public chip::rpc::FabricBridge
pw::Status AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) override;
pw::Status RemoveSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) override;
pw::Status ActiveChanged(const chip_rpc_KeepActiveChanged & request, pw_protobuf_Empty & response) override;
pw::Status AdminCommissioningAttributeChanged(const chip_rpc_AdministratorCommissioningChanged & request,
pw_protobuf_Empty & response) override;
};

pw::Status FabricBridge::AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response)
Expand Down Expand Up @@ -160,6 +162,44 @@ pw::Status FabricBridge::ActiveChanged(const chip_rpc_KeepActiveChanged & reques
return pw::OkStatus();
}

pw::Status FabricBridge::AdminCommissioningAttributeChanged(const chip_rpc_AdministratorCommissioningChanged & request,
pw_protobuf_Empty & response)
{
NodeId nodeId = request.node_id;
ChipLogProgress(NotSpecified, "Received CADMIN attribut change: " ChipLogFormatX64, ChipLogValueX64(nodeId));

auto * device = BridgeDeviceMgr().GetDeviceByNodeId(nodeId);
if (device == nullptr)
{
ChipLogError(NotSpecified, "Could not find bridged device associated with nodeId=0x" ChipLogFormatX64,
ChipLogValueX64(nodeId));
return pw::Status::NotFound();
}

BridgedDevice::AdminCommissioningAttributes adminCommissioningAttributes;

uint32_t max_window_status_value =
static_cast<uint32_t>(chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kUnknownEnumValue);
VerifyOrReturnValue(request.window_status < max_window_status_value, pw::Status::InvalidArgument());
adminCommissioningAttributes.commissioningWindowStatus =
static_cast<chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum>(request.window_status);
if (request.has_opener_fabric_index)
{
VerifyOrReturnValue(request.opener_fabric_index >= chip::kMinValidFabricIndex, pw::Status::InvalidArgument());
VerifyOrReturnValue(request.opener_fabric_index <= chip::kMaxValidFabricIndex, pw::Status::InvalidArgument());
adminCommissioningAttributes.openerFabricIndex = static_cast<FabricIndex>(request.opener_fabric_index);
}

if (request.has_opener_vendor_id)
{
VerifyOrReturnValue(request.opener_vendor_id != chip::VendorId::NotSpecified, pw::Status::InvalidArgument());
adminCommissioningAttributes.openerVendorId = static_cast<chip::VendorId>(request.opener_vendor_id);
}

device->SetAdminCommissioningAttributes(adminCommissioningAttributes);
return pw::OkStatus();
}

FabricBridge fabric_bridge_service;
#endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE

Expand Down

0 comments on commit 6b5a2ce

Please sign in to comment.