#include "CommissionerControl.h" #include using namespace ::chip; void CommissionerControl::Init(Controller::DeviceCommissioner & commissioner, NodeId nodeId, EndpointId endpointId) { // Ensure that mCommissioner is not already initialized VerifyOrDie(mCommissioner == nullptr); ChipLogProgress(NotSpecified, "Initilize CommissionerControl"); mCommissioner = &commissioner; mDestinationId = nodeId; mEndpointId = endpointId; } CHIP_ERROR CommissionerControl::RequestCommissioningApproval(uint64_t requestId, uint16_t vendorId, uint16_t productId, Optional label) { VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE); ChipLogProgress(NotSpecified, "Sending RequestCommissioningApproval to node " ChipLogFormatX64, ChipLogValueX64(mDestinationId)); mRequestCommissioningApproval.requestID = requestId; mRequestCommissioningApproval.vendorID = static_cast(vendorId); mRequestCommissioningApproval.productID = productId; if (label.HasValue()) { VerifyOrReturnError(label.Value().size() <= kMaxDeviceLabelLength, CHIP_ERROR_BUFFER_TOO_SMALL); memcpy(mLabelBuffer, label.Value().data(), label.Value().size()); mRequestCommissioningApproval.label = Optional>(CharSpan(mLabelBuffer, label.Value().size())); } mCommandType = CommandType::kRequestCommissioningApproval; return mCommissioner->GetConnectedDevice(mDestinationId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); } CHIP_ERROR CommissionerControl::CommissionNode(uint64_t requestId, uint16_t responseTimeoutSeconds) { VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE); ChipLogProgress(NotSpecified, "Sending CommissionNode to node " ChipLogFormatX64, ChipLogValueX64(mDestinationId)); mCommissionNode.requestID = requestId; mCommissionNode.responseTimeoutSeconds = responseTimeoutSeconds; mCommandType = CommandType::kCommissionNode; return mCommissioner->GetConnectedDevice(mDestinationId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); } void CommissionerControl::OnResponse(app::CommandSender * client, const app::ConcreteCommandPath & path, const app::StatusIB & status, TLV::TLVReader * data) { ChipLogProgress(NotSpecified, "CommissionerControl: OnResponse."); CHIP_ERROR error = status.ToChipError(); if (CHIP_NO_ERROR != error) { ChipLogError(NotSpecified, "Response Failure: %s", ErrorStr(error)); return; } if (data != nullptr) { DeviceMgr().HandleCommandResponse(path, *data); } } void CommissionerControl::OnError(const app::CommandSender * client, CHIP_ERROR error) { // Handle the error, then reset mCommandSender ChipLogProgress(NotSpecified, "CommissionerControl: OnError: Error: %s", ErrorStr(error)); } void CommissionerControl::OnDone(app::CommandSender * client) { ChipLogProgress(NotSpecified, "CommissionerControl: OnDone."); switch (mCommandType) { case CommandType::kRequestCommissioningApproval: ChipLogProgress(NotSpecified, "CommissionerControl: Command RequestCommissioningApproval has been successfully processed."); break; case CommandType::kCommissionNode: ChipLogProgress(NotSpecified, "CommissionerControl: Command CommissionNode has been successfully processed."); break; default: ChipLogError(NotSpecified, "CommissionerControl: Unknown or unhandled command type in OnDone."); break; } // Reset command type to undefined after processing is done mCommandType = CommandType::kUndefined; // Ensure that mCommandSender is cleaned up after it is done mCommandSender.reset(); } CHIP_ERROR CommissionerControl::SendCommandForType(CommandType commandType, DeviceProxy * device) { switch (commandType) { case CommandType::kRequestCommissioningApproval: return SendCommand(device, mEndpointId, app::Clusters::CommissionerControl::Id, app::Clusters::CommissionerControl::Commands::RequestCommissioningApproval::Id, mRequestCommissioningApproval); case CommandType::kCommissionNode: return SendCommand(device, mEndpointId, app::Clusters::CommissionerControl::Id, app::Clusters::CommissionerControl::Commands::CommissionNode::Id, mCommissionNode); default: return CHIP_ERROR_INVALID_ARGUMENT; } } void CommissionerControl::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) { CommissionerControl * self = reinterpret_cast(context); VerifyOrReturn(self != nullptr, ChipLogError(NotSpecified, "OnDeviceConnectedFn: context is null")); OperationalDeviceProxy device(&exchangeMgr, sessionHandle); CHIP_ERROR err = self->SendCommandForType(self->mCommandType, &device); if (err != CHIP_NO_ERROR) { ChipLogError(NotSpecified, "Failed to send CommissionerControl command."); self->OnDone(nullptr); } } void CommissionerControl::OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR err) { LogErrorOnFailure(err); CommissionerControl * self = reinterpret_cast(context); VerifyOrReturn(self != nullptr, ChipLogError(NotSpecified, "OnDeviceConnectedFn: context is null")); self->OnDone(nullptr); }