diff --git a/examples/common/pigweed/protos/fabric_admin_service.proto b/examples/common/pigweed/protos/fabric_admin_service.proto index 7c99deb7ad3ef6..3c311493d1c6f3 100644 --- a/examples/common/pigweed/protos/fabric_admin_service.proto +++ b/examples/common/pigweed/protos/fabric_admin_service.proto @@ -34,6 +34,6 @@ message OperationStatus { service FabricAdmin { rpc OpenCommissioningWindow(DeviceCommissioningWindowInfo) returns (OperationStatus){} - rpc ReverseCommissionBridge(DeviceCommissioningInfo) returns (pw.protobuf.Empty){} + rpc CommissionNode(DeviceCommissioningInfo) returns (pw.protobuf.Empty){} rpc KeepActive(KeepActiveParameters) returns (pw.protobuf.Empty){} } diff --git a/examples/common/pigweed/rpc_services/FabricAdmin.h b/examples/common/pigweed/rpc_services/FabricAdmin.h index 322de6f592a29e..256b06c73e4fd5 100644 --- a/examples/common/pigweed/rpc_services/FabricAdmin.h +++ b/examples/common/pigweed/rpc_services/FabricAdmin.h @@ -40,7 +40,7 @@ class FabricAdmin : public pw_rpc::nanopb::FabricAdmin::Service return pw::Status::Unimplemented(); } - virtual pw::Status ReverseCommissionBridge(const chip_rpc_DeviceCommissioningInfo & request, pw_protobuf_Empty & response) + virtual pw::Status CommissionNode(const chip_rpc_DeviceCommissioningInfo & request, pw_protobuf_Empty & response) { return pw::Status::Unimplemented(); } diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index 13627d2e404ad8..3f672bd17cadb7 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -56,12 +56,12 @@ void DeviceManager::Init() NodeId DeviceManager::GetNextAvailableNodeId() { mLastUsedNodeId++; - VerifyOrDieWithMsg(mLastUsedNodeId < std::numeric_limits::max(), NotSpecified, "No more available NodeIds."); + VerifyOrDieWithMsg(mLastUsedNodeId < std::numeric_limits::max(), NotSpecified, "No more available NodeIds."); return mLastUsedNodeId; } -void DeviceManager::UpdateLastUsedNodeId(chip::NodeId nodeId) +void DeviceManager::UpdateLastUsedNodeId(NodeId nodeId) { if (nodeId > mLastUsedNodeId) { @@ -159,7 +159,7 @@ void DeviceManager::PairRemoteFabricBridge(NodeId nodeId, const char * deviceRem PushCommand(commandBuilder.c_str()); } -void DeviceManager::PairRemoteDevice(chip::NodeId nodeId, const char * payload) +void DeviceManager::PairRemoteDevice(NodeId nodeId, const char * payload) { StringBuilder commandBuilder; @@ -238,7 +238,7 @@ void DeviceManager::ReadSupportedDeviceCategories() PushCommand(commandBuilder.c_str()); } -void DeviceManager::StartReverseCommissioning() +void DeviceManager::RequestCommissioningApproval() { ChipLogProgress(NotSpecified, "Starting reverse commissioning for bridge device: NodeId: " ChipLogFormatX64, ChipLogValueX64(mRemoteBridgeNodeId)); @@ -255,7 +255,36 @@ void DeviceManager::StartReverseCommissioning() PushCommand(commandBuilder.c_str()); } -void DeviceManager::CommissionApprovedRequest(uint64_t requestId, uint16_t responseTimeoutSeconds) +void DeviceManager::HandleCommissioningRequestResult(TLV::TLVReader * data) +{ + ChipLogProgress(NotSpecified, "CommissioningRequestResult event received."); + + CommissionerControl::Events::CommissioningRequestResult::DecodableType value; + CHIP_ERROR error = app::DataModel::Decode(*data, value); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to decode event value. Error: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + + if (value.requestId != mRequestId) + { + ChipLogError(NotSpecified, "The RequestId does not match the RequestId provided to RequestCommissioningApproval"); + return; + } + + if (value.statusCode != static_cast(Protocols::InteractionModel::Status::Success)) + { + ChipLogError(NotSpecified, "The server is not ready to begin commissioning the requested device"); + return; + } + + // The server is ready to begin commissioning the requested device, request the Commissioner Control Server to begin + // commissioning a previously approved request. + SendCommissionNodeRequest(value.requestId, kResponseTimeoutSeconds); +} + +void DeviceManager::SendCommissionNodeRequest(uint64_t requestId, uint16_t responseTimeoutSeconds) { ChipLogProgress(NotSpecified, "Request the Commissioner Control Server to begin commissioning a previously approved request."); @@ -266,6 +295,35 @@ void DeviceManager::CommissionApprovedRequest(uint64_t requestId, uint16_t respo PushCommand(commandBuilder.c_str()); } +void DeviceManager::HandleReverseOpenCommissioningWindow(TLV::TLVReader * data) +{ + CommissionerControl::Commands::ReverseOpenCommissioningWindow::DecodableType value; + CHIP_ERROR error = app::DataModel::Decode(*data, value); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to decode command response value. Error: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + + // Log all fields + ChipLogProgress(NotSpecified, "DecodableType fields:"); + ChipLogProgress(NotSpecified, " commissioningTimeout: %u", value.commissioningTimeout); + ChipLogProgress(NotSpecified, " discriminator: %u", value.discriminator); + ChipLogProgress(NotSpecified, " iterations: %u", value.iterations); + + char verifierHex[Crypto::kSpake2p_VerifierSerialized_Length * 2 + 1]; + Encoding::BytesToHex(value.PAKEPasscodeVerifier.data(), value.PAKEPasscodeVerifier.size(), verifierHex, sizeof(verifierHex), + Encoding::HexFlags::kNullTerminate); + ChipLogProgress(NotSpecified, " PAKEPasscodeVerifier: %s", verifierHex); + + char saltHex[Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1]; + Encoding::BytesToHex(value.salt.data(), value.salt.size(), saltHex, sizeof(saltHex), Encoding::HexFlags::kNullTerminate); + ChipLogProgress(NotSpecified, " salt: %s", saltHex); + + OpenDeviceCommissioningWindow(mLocalBridgeNodeId, value.commissioningTimeout, value.iterations, value.discriminator, saltHex, + verifierHex); +} + void DeviceManager::HandleAttributeData(const app::ConcreteDataAttributePath & path, TLV::TLVReader * data) { if (path.mClusterId == CommissionerControl::Id && @@ -284,7 +342,7 @@ void DeviceManager::HandleAttributeData(const app::ConcreteDataAttributePath & p if (value.Has(CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization)) { ChipLogProgress(NotSpecified, "Remote Fabric-Bridge supports Fabric Synchronization, start reverse commissioning."); - StartReverseCommissioning(); + RequestCommissioningApproval(); } return; @@ -399,73 +457,23 @@ void DeviceManager::HandleAttributeData(const app::ConcreteDataAttributePath & p } } -void DeviceManager::HandleEventData(const chip::app::EventHeader & header, chip::TLV::TLVReader * data) +void DeviceManager::HandleEventData(const app::EventHeader & header, TLV::TLVReader * data) { if (header.mPath.mClusterId != CommissionerControl::Id || header.mPath.mEventId != CommissionerControl::Events::CommissioningRequestResult::Id) { - return; - } - - ChipLogProgress(NotSpecified, "CommissioningRequestResult event received."); - - CommissionerControl::Events::CommissioningRequestResult::DecodableType value; - CHIP_ERROR error = app::DataModel::Decode(*data, value); - if (error != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to decode event value. Error: %" CHIP_ERROR_FORMAT, error.Format()); - return; - } - - if (value.requestId != mRequestId) - { - ChipLogError(NotSpecified, "The RequestId does not match the RequestId provided to RequestCommissioningApproval"); - return; + HandleCommissioningRequestResult(data); } - - if (value.statusCode != static_cast(Protocols::InteractionModel::Status::Success)) - { - ChipLogError(NotSpecified, "The server is not ready to begin commissioning the requested device"); - return; - } - - // The server is ready to begin commissioning the requested device, request the Commissioner Control Server to begin - // commissioning a previously approved request. - CommissionApprovedRequest(value.requestId, kResponseTimeoutSeconds); } -void DeviceManager::HandleCommandResponse(const chip::app::ConcreteCommandPath & path, chip::TLV::TLVReader * data) +void DeviceManager::HandleCommandResponse(const app::ConcreteCommandPath & path, TLV::TLVReader * data) { ChipLogProgress(NotSpecified, "Command Response received."); if (path.mClusterId == CommissionerControl::Id && path.mCommandId == CommissionerControl::Commands::ReverseOpenCommissioningWindow::Id) { - CommissionerControl::Commands::ReverseOpenCommissioningWindow::DecodableType value; - CHIP_ERROR error = app::DataModel::Decode(*data, value); - if (error != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to decode command response value. Error: %" CHIP_ERROR_FORMAT, error.Format()); - return; - } - - // Log all fields - ChipLogProgress(NotSpecified, "DecodableType fields:"); - ChipLogProgress(NotSpecified, " commissioningTimeout: %u", value.commissioningTimeout); - ChipLogProgress(NotSpecified, " discriminator: %u", value.discriminator); - ChipLogProgress(NotSpecified, " iterations: %u", value.iterations); - - char verifierHex[Crypto::kSpake2p_VerifierSerialized_Length * 2 + 1]; - Encoding::BytesToHex(value.PAKEPasscodeVerifier.data(), value.PAKEPasscodeVerifier.size(), verifierHex, sizeof(verifierHex), - Encoding::HexFlags::kNullTerminate); - ChipLogProgress(NotSpecified, " PAKEPasscodeVerifier: %s", verifierHex); - - char saltHex[Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1]; - Encoding::BytesToHex(value.salt.data(), value.salt.size(), saltHex, sizeof(saltHex), Encoding::HexFlags::kNullTerminate); - ChipLogProgress(NotSpecified, " salt: %s", saltHex); - - OpenDeviceCommissioningWindow(mLocalBridgeNodeId, value.commissioningTimeout, value.iterations, value.discriminator, - saltHex, verifierHex); + HandleReverseOpenCommissioningWindow(data); } } diff --git a/examples/fabric-admin/device_manager/DeviceManager.h b/examples/fabric-admin/device_manager/DeviceManager.h index 5d9f98e0b4c799..b6c7dc0e657b51 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.h +++ b/examples/fabric-admin/device_manager/DeviceManager.h @@ -148,12 +148,8 @@ class DeviceManager : public PairingDelegate void SubscribeRemoteFabricBridge(); - void StartReverseCommissioning(); - void ReadSupportedDeviceCategories(); - void CommissionApprovedRequest(uint64_t requestId, uint16_t responseTimeoutSeconds); - void HandleAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data); void HandleEventData(const chip::app::EventHeader & header, chip::TLV::TLVReader * data); @@ -165,6 +161,14 @@ class DeviceManager : public PairingDelegate private: friend DeviceManager & DeviceMgr(); + void RequestCommissioningApproval(); + + void HandleCommissioningRequestResult(chip::TLV::TLVReader * data); + + void SendCommissionNodeRequest(uint64_t requestId, uint16_t responseTimeoutSeconds); + + void HandleReverseOpenCommissioningWindow(chip::TLV::TLVReader * data); + static DeviceManager sInstance; chip::NodeId mLastUsedNodeId = 0; diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index fa3045de28d06e..f240feda22a2d4 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -92,12 +92,12 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate return pw::OkStatus(); } - pw::Status ReverseCommissionBridge(const chip_rpc_DeviceCommissioningInfo & request, pw_protobuf_Empty & response) override + pw::Status CommissionNode(const chip_rpc_DeviceCommissioningInfo & request, pw_protobuf_Empty & response) override { char saltHex[Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1]; Encoding::BytesToHex(request.salt.bytes, request.salt.size, saltHex, sizeof(saltHex), Encoding::HexFlags::kNullTerminate); - ChipLogProgress(NotSpecified, "Received ReverseCommissionBridge request"); + ChipLogProgress(NotSpecified, "Received CommissionNode request"); SetupPayload setupPayload = SetupPayload(); @@ -109,7 +109,7 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate discriminator.SetLongValue(request.discriminator); setupPayload.discriminator = discriminator; - char payloadBuffer[kMaxManaulCodeLength + 1]; + char payloadBuffer[kMaxManualCodeLength + 1]; MutableCharSpan manualCode(payloadBuffer); CHIP_ERROR error = ManualSetupPayloadGenerator(setupPayload).payloadDecimalStringRepresentation(manualCode); @@ -117,6 +117,8 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate { NodeId nodeId = DeviceMgr().GetNextAvailableNodeId(); + // After responding with RequestCommissioningApproval to the node where the client initiated the + // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. usleep(kCommissionPrepareTimeMs * 1000); DeviceMgr().PairRemoteDevice(nodeId, payloadBuffer); diff --git a/examples/fabric-bridge-app/linux/CommissionerControl.cpp b/examples/fabric-bridge-app/linux/CommissionerControl.cpp index e02f1947e03984..9f3180668de42c 100644 --- a/examples/fabric-bridge-app/linux/CommissionerControl.cpp +++ b/examples/fabric-bridge-app/linux/CommissionerControl.cpp @@ -126,18 +126,18 @@ CHIP_ERROR CommissionerControlDelegate::GetCommissioningWindowParams(Commissioni return CHIP_NO_ERROR; } -CHIP_ERROR CommissionerControlDelegate::ReverseCommissionNode(const CommissioningWindowParams & params, - const Optional & ipAddress, const Optional & port) +CHIP_ERROR CommissionerControlDelegate::HandleCommissionNode(const CommissioningWindowParams & params, + const Optional & ipAddress, const Optional & port) { - ChipLogProgress(NotSpecified, "CommissionerControlDelegate::ReverseCommissionNode"); + ChipLogProgress(NotSpecified, "CommissionerControlDelegate::HandleCommissionNode"); #if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE - return ReverseCommissionBridge(Controller::CommissioningWindowPasscodeParams() - .SetSetupPIN(kSetupPinCode) - .SetTimeout(params.commissioningTimeout) - .SetDiscriminator(params.discriminator) - .SetIteration(params.iterations) - .SetSalt(params.salt)); + return CommissionNode(Controller::CommissioningWindowPasscodeParams() + .SetSetupPIN(kSetupPinCode) + .SetTimeout(params.commissioningTimeout) + .SetDiscriminator(params.discriminator) + .SetIteration(params.iterations) + .SetSalt(params.salt)); #else ChipLogProgress(NotSpecified, "Failed to reverse commission bridge: PW_RPC_FABRIC_BRIDGE_SERVICE not defined"); return CHIP_ERROR_NOT_IMPLEMENTED; diff --git a/examples/fabric-bridge-app/linux/RpcClient.cpp b/examples/fabric-bridge-app/linux/RpcClient.cpp index 1392bca7f02c2b..b3c82303beb8f5 100644 --- a/examples/fabric-bridge-app/linux/RpcClient.cpp +++ b/examples/fabric-bridge-app/linux/RpcClient.cpp @@ -163,7 +163,7 @@ OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams para } CHIP_ERROR -ReverseCommissionBridge(chip::Controller::CommissioningWindowPasscodeParams params) +CommissionNode(chip::Controller::CommissioningWindowPasscodeParams params) { chip_rpc_DeviceCommissioningInfo device; device.setup_pin = params.GetSetupPIN(); @@ -176,7 +176,7 @@ ReverseCommissionBridge(chip::Controller::CommissioningWindowPasscodeParams para // 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 = fabricAdminClient.ReverseCommissionBridge(device, RpcCompletedWithEmptyResponse); + auto call = fabricAdminClient.CommissionNode(device, RpcCompletedWithEmptyResponse); if (!call.active()) { diff --git a/examples/fabric-bridge-app/linux/include/CommissionerControl.h b/examples/fabric-bridge-app/linux/include/CommissionerControl.h index e2347a8c5eb640..633be761ba1004 100644 --- a/examples/fabric-bridge-app/linux/include/CommissionerControl.h +++ b/examples/fabric-bridge-app/linux/include/CommissionerControl.h @@ -32,8 +32,8 @@ class CommissionerControlDelegate : public Delegate CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) override; CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) override; CHIP_ERROR GetCommissioningWindowParams(CommissioningWindowParams & outParams) override; - CHIP_ERROR ReverseCommissionNode(const CommissioningWindowParams & params, const Optional & ipAddress, - const Optional & port) override; + CHIP_ERROR HandleCommissionNode(const CommissioningWindowParams & params, const Optional & ipAddress, + const Optional & port) override; ~CommissionerControlDelegate() = default; diff --git a/examples/fabric-bridge-app/linux/include/RpcClient.h b/examples/fabric-bridge-app/linux/include/RpcClient.h index d4b612d0275c46..87ccba24f645dc 100644 --- a/examples/fabric-bridge-app/linux/include/RpcClient.h +++ b/examples/fabric-bridge-app/linux/include/RpcClient.h @@ -58,7 +58,7 @@ CHIP_ERROR OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams params); /** - * Reverse commission the bridge using the specified parameters. + * Commission a node using the specified parameters. * * @param params Params for commissioning the device using passcode. * @return CHIP_ERROR An error code indicating the success or failure of the operation. @@ -66,6 +66,6 @@ OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams para * - CHIP_ERROR_INTERNAL: An internal error occurred. */ CHIP_ERROR -ReverseCommissionBridge(chip::Controller::CommissioningWindowPasscodeParams params); +CommissionNode(chip::Controller::CommissioningWindowPasscodeParams params); CHIP_ERROR KeepActive(chip::NodeId nodeId, uint32_t stayActiveDurationMs); diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp index d8a655f6afb241..4df397326894ed 100644 --- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp +++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp @@ -71,15 +71,15 @@ void RunDeferredCommissionNode(intptr_t commandArg) if (delegate != nullptr) { - CHIP_ERROR err = delegate->ReverseCommissionNode(info->params, info->ipAddress.GetIPAddress(), info->port); + CHIP_ERROR err = delegate->HandleCommissionNode(info->params, info->ipAddress.GetIPAddress(), info->port); if (err != CHIP_NO_ERROR) { - ChipLogError(Zcl, "ReverseCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format()); + ChipLogError(Zcl, "HandleCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format()); } } else { - ChipLogError(Zcl, "No delegate available for ReverseCommissionNode"); + ChipLogError(Zcl, "No delegate available for HandleCommissionNode"); } delete info; diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h index 5e2422f5ebe018..60a4e81a93c3af 100644 --- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h +++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h @@ -101,9 +101,6 @@ class Delegate /** * @brief Validate a commission node command. * - * This command is sent by a client to request that the server begins commissioning a previously - * approved request. - * * The server SHALL return FAILURE if the CommissionNode command is not sent from the same * NodeId as the RequestCommissioningApproval or if the provided RequestId to CommissionNode * does not match the value provided to RequestCommissioningApproval. @@ -128,19 +125,17 @@ class Delegate virtual CHIP_ERROR GetCommissioningWindowParams(CommissioningWindowParams & outParams) = 0; /** - * @brief Reverse the commission node process. + * @brief Handle a commission node request. * - * When received within the timeout specified by CommissionNode, the client SHALL open a - * commissioning window on the node which the client called RequestCommissioningApproval to - * have commissioned. + * Commission a node specified by the previously approved request. * * @param params The parameters for the commissioning window. * @param ipAddress Optional IP address for the commissioning window. * @param port Optional port for the commissioning window. * @return CHIP_ERROR indicating the success or failure of the operation. */ - virtual CHIP_ERROR ReverseCommissionNode(const CommissioningWindowParams & params, const Optional & ipAddress, - const Optional & port) = 0; + virtual CHIP_ERROR HandleCommissionNode(const CommissioningWindowParams & params, const Optional & ipAddress, + const Optional & port) = 0; virtual ~Delegate() = default; };