From fa799d987a5da9d7f1a4adb70a93f73a45fa7f1e Mon Sep 17 00:00:00 2001 From: Cecille Freeman Date: Fri, 28 Jan 2022 16:55:33 -0500 Subject: [PATCH] Use multi-endpoint wildcard to simplify commissioning --- src/app/AttributeCache.h | 1 + src/controller/AutoCommissioner.cpp | 129 ++++-------------- src/controller/AutoCommissioner.h | 10 +- src/controller/CHIPDeviceController.cpp | 172 +++++++++++------------- src/controller/CHIPDeviceController.h | 47 ++++--- src/controller/CommissioningDelegate.h | 32 ++--- 6 files changed, 141 insertions(+), 250 deletions(-) diff --git a/src/app/AttributeCache.h b/src/app/AttributeCache.h index 37fb41ba759e04..a2965a644d5269 100644 --- a/src/app/AttributeCache.h +++ b/src/app/AttributeCache.h @@ -279,6 +279,7 @@ class AttributeCache : protected ReadClient::Callback } } } + return CHIP_NO_ERROR; } /* diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp index 4fb172e51c9e48..44a59bac8cf5af 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -96,14 +96,6 @@ CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParam return CHIP_NO_ERROR; } -bool AutoCommissioner::NetworkClusterUseable() -{ - return (mNetworkTechnology.Has(app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kWiFiNetworkInterface) && - mParams.GetWiFiCredentials().HasValue()) || - (mNetworkTechnology.Has(app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kThreadNetworkInterface) && - mParams.GetThreadOperationalDataset().HasValue()); -} - CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStage currentStage, CHIP_ERROR & lastErr) { if (lastErr != CHIP_NO_ERROR) @@ -111,15 +103,6 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStag return CommissioningStage::kCleanup; } - bool checkNetworkTechnology = false; - if (currentStage == CommissioningStage::kCheckEndpointIsCommissionable && mNeedsNetworkSetup && mNetworkEndpoint == mEndpoint) - { - // We found a networking cluster on the current endpoint, but have not yet checked the feature map to - // see what network technologies are supported. - checkNetworkTechnology = true; - } - - mEndpoint = 0; switch (currentStage) { case CommissioningStage::kSecurePairing: @@ -129,12 +112,7 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStag case CommissioningStage::kReadProductId: return CommissioningStage::kReadSoftwareVersion; case CommissioningStage::kReadSoftwareVersion: - return CommissioningStage::kGetPartsList; - case CommissioningStage::kGetPartsList: - return CommissioningStage::kCheckEndpointIsCommissionable; - case CommissioningStage::kCheckEndpointIsCommissionable: - if (checkNetworkTechnology) - { + if(mNeedsNetworkSetup) { return CommissioningStage::kGetNetworkTechnology; } else @@ -142,25 +120,7 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStag return CommissioningStage::kArmFailsafe; } case CommissioningStage::kGetNetworkTechnology: - if (mNeedsNetworkSetup && !NetworkClusterUseable()) - { - if (mAllEndpoints.numEndpoints > 0) - { - // Cycle through the list of endpoints from the end, checking for network cluster. - mEndpoint = mAllEndpoints.endpoints[--mAllEndpoints.numEndpoints]; - return CommissioningStage::kCheckEndpointIsCommissionable; - } - else - { - ChipLogError(Controller, "Unable to find a suitable network commissioning cluster for the given parameters"); - lastErr = CHIP_ERROR_INVALID_ARGUMENT; - return CommissioningStage::kCleanup; - } - } - else - { - return CommissioningStage::kArmFailsafe; - } + return CommissioningStage::kArmFailsafe; case CommissioningStage::kArmFailsafe: return CommissioningStage::kConfigRegulatory; case CommissioningStage::kConfigRegulatory: @@ -185,16 +145,11 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStag // operational network because the provisioning of certificates will trigger the device to start operational advertising. if (mNeedsNetworkSetup) { - mEndpoint = mNetworkEndpoint; - if (mParams.GetWiFiCredentials().HasValue() && - mNetworkTechnology.Has( - chip::app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kWiFiNetworkInterface)) + if (mParams.GetWiFiCredentials().HasValue() && mNetworkEndpoints.wifi != kInvalidEndpointId) { return CommissioningStage::kWiFiNetworkSetup; } - else if (mParams.GetThreadOperationalDataset().HasValue() && - mNetworkTechnology.Has( - chip::app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kThreadNetworkInterface)) + else if (mParams.GetThreadOperationalDataset().HasValue() && mNetworkEndpoints.thread != kInvalidEndpointId) { return CommissioningStage::kThreadNetworkSetup; } @@ -215,9 +170,7 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStag #endif } case CommissioningStage::kWiFiNetworkSetup: - mEndpoint = mNetworkEndpoint; - if (mParams.GetThreadOperationalDataset().HasValue() && - mNetworkTechnology.Has(chip::app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kThreadNetworkInterface)) + if (mParams.GetThreadOperationalDataset().HasValue() && mNetworkEndpoints.thread != kInvalidEndpointId) { return CommissioningStage::kThreadNetworkSetup; } @@ -226,9 +179,7 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStag return CommissioningStage::kWiFiNetworkEnable; } case CommissioningStage::kThreadNetworkSetup: - mEndpoint = mNetworkEndpoint; - if (mParams.GetWiFiCredentials().HasValue() && - mNetworkTechnology.Has(chip::app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kWiFiNetworkInterface)) + if (mParams.GetWiFiCredentials().HasValue() && mNetworkEndpoints.wifi != kInvalidEndpointId) { return CommissioningStage::kWiFiNetworkEnable; } @@ -238,9 +189,7 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStag } case CommissioningStage::kWiFiNetworkEnable: - mEndpoint = mNetworkEndpoint; - if (mParams.GetThreadOperationalDataset().HasValue() && - mNetworkTechnology.Has(chip::app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kThreadNetworkInterface)) + if (mParams.GetThreadOperationalDataset().HasValue() && mNetworkEndpoints.thread != kInvalidEndpointId) { return CommissioningStage::kThreadNetworkEnable; } @@ -249,7 +198,6 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStag return CommissioningStage::kFindOperational; } case CommissioningStage::kThreadNetworkEnable: - mEndpoint = mNetworkEndpoint; // TODO: I dont think this is to spec - not sure where we'd have a commissioner that doesn't have dnssd. #if CHIP_DEVICE_CONFIG_ENABLE_DNSSD return CommissioningStage::kFindOperational; @@ -272,6 +220,21 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStag return CommissioningStage::kError; } +EndpointId AutoCommissioner::GetEndpoint(const CommissioningStage & stage) { + switch(stage) { + case CommissioningStage::kWiFiNetworkSetup: + case CommissioningStage::kWiFiNetworkEnable: + return mNetworkEndpoints.wifi; + case CommissioningStage::kThreadNetworkSetup: + case CommissioningStage::kThreadNetworkEnable: + return mNetworkEndpoints.thread; + case CommissioningStage::kGetNetworkTechnology: + return kInvalidEndpointId; + default: + return 0; + } +} + void AutoCommissioner::StartCommissioning(CommissioneeDeviceProxy * proxy) { // TODO: check that there is no commissioning in progress currently. @@ -287,7 +250,7 @@ void AutoCommissioner::StartCommissioning(CommissioneeDeviceProxy * proxy) Transport::Type::kBle; CHIP_ERROR err = CHIP_NO_ERROR; CommissioningStage nextStage = GetNextCommissioningStage(CommissioningStage::kSecurePairing, err); - mCommissioner->PerformCommissioningStep(mCommissioneeDeviceProxy, nextStage, mParams, this, 0, GetCommandTimeout(nextStage)); + mCommissioner->PerformCommissioningStep(mCommissioneeDeviceProxy, nextStage, mParams, this, GetEndpoint(nextStage), GetCommandTimeout(nextStage)); } Optional AutoCommissioner::GetCommandTimeout(CommissioningStage stage) @@ -340,15 +303,7 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio { if (err != CHIP_NO_ERROR) { - if (report.stageCompleted == CommissioningStage::kCheckEndpointIsCommissionable && mEndpoint != 0) - { - ChipLogError(Controller, "No descriptor cluster found for endpoint %u, ignoring", mEndpoint); - err = CHIP_NO_ERROR; - } - else - { - ChipLogError(Controller, "Failed to perform commissioning step %d", static_cast(report.stageCompleted)); - } + ChipLogError(Controller, "Failed to perform commissioning step %d", static_cast(report.stageCompleted)); } else { @@ -363,37 +318,8 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio case CommissioningStage::kReadSoftwareVersion: mSoftwareVersion = report.Get().softwareVersion; break; - case CommissioningStage::kGetPartsList: - mAllEndpoints = report.Get(); - break; - case CommissioningStage::kCheckEndpointIsCommissionable: - if (mEndpoint == 0 && !report.Get().isCommissionable) - { - ChipLogError(Controller, "Device endpoint is not commissionable"); - return CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR; - } - if (report.Get().hasNetworkCluster) - { - mNetworkEndpoint = mEndpoint; - } - break; case CommissioningStage::kGetNetworkTechnology: - mNetworkTechnology.SetRaw(report.Get().features); - // Only one of these features can be set at a time. - if (!mNetworkTechnology.HasOnly( - chip::app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kWiFiNetworkInterface) && - !mNetworkTechnology.HasOnly( - chip::app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kThreadNetworkInterface) && - mNetworkTechnology.HasOnly( - chip::app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kEthernetNetworkInterface)) - { - ChipLogError( - Controller, - "Network Commissioning cluster is malformed - more than one network technology is specified (0x%" PRIX32 ")", - report.Get().features); - err = CHIP_ERROR_INTEGRITY_CHECK_FAILED; - break; - } + mNetworkEndpoints = report.Get(); break; case CommissioningStage::kSendPAICertificateRequest: SetPAI(report.Get().certificate); @@ -435,8 +361,7 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio mCommissioneeDeviceProxy = nullptr; mOperationalDeviceProxy = nullptr; mParams = CommissioningParameters(); - mAllEndpoints = EndpointParts(); - mNetworkEndpoint = 0; + mNetworkEndpoints = NetworkClusters(); return CHIP_NO_ERROR; default: break; @@ -464,7 +389,7 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio mParams.SetCompletionStatus(err); // TODO: Get real endpoint - mCommissioner->PerformCommissioningStep(proxy, nextStage, mParams, this, mEndpoint, GetCommandTimeout(nextStage)); + mCommissioner->PerformCommissioningStep(proxy, nextStage, mParams, this, GetEndpoint(nextStage), GetCommandTimeout(nextStage)); return CHIP_NO_ERROR; } diff --git a/src/controller/AutoCommissioner.h b/src/controller/AutoCommissioner.h index 8da18c06d6697b..158d460c7f2a92 100644 --- a/src/controller/AutoCommissioner.h +++ b/src/controller/AutoCommissioner.h @@ -51,15 +51,13 @@ class AutoCommissioner : public CommissioningDelegate CHIP_ERROR NOCChainGenerated(ByteSpan noc, ByteSpan icac, ByteSpan rcac, AesCcm128KeySpan ipk, NodeId adminSubject); Optional GetCommandTimeout(CommissioningStage stage); - bool NetworkClusterUseable(); + EndpointId GetEndpoint(const CommissioningStage & stage); DeviceCommissioner * mCommissioner; CommissioneeDeviceProxy * mCommissioneeDeviceProxy = nullptr; OperationalDeviceProxy * mOperationalDeviceProxy = nullptr; OperationalCredentialsDelegate * mOperationalCredentialsDelegate = nullptr; CommissioningParameters mParams = CommissioningParameters(); - EndpointParts mAllEndpoints; - EndpointId mEndpoint; VendorId mVendorId; uint16_t mProductId; uint32_t mSoftwareVersion; @@ -68,12 +66,8 @@ class AutoCommissioner : public CommissioningDelegate uint8_t mCredentials[CommissioningParameters::kMaxCredentialsLen]; uint8_t mThreadOperationalDataset[CommissioningParameters::kMaxThreadDatasetLen]; - // We only commission one network endpoint even if the device and the parameters are capable of setting up > 1. - // This is sufficient to get the device onto the network. Additional network setup can be done after commissioning - // if required. bool mNeedsNetworkSetup = false; - BitFlags mNetworkTechnology; - EndpointId mNetworkEndpoint = 0xFFFF; + NetworkClusters mNetworkEndpoints; // TODO: Why were the nonces statically allocated, but the certs dynamically allocated? uint8_t * mDAC = nullptr; diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 9ac85db9c857e3..feed5d37d24d11 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -36,6 +36,8 @@ #include #include +#include +#include #include #if CONFIG_DEVICE_LAYER @@ -460,7 +462,7 @@ CHIP_ERROR DeviceController::ComputePASEVerifier(uint32_t iterations, uint32_t s CHIP_ERROR DeviceController::OpenCommissioningWindowWithCallback(NodeId deviceId, uint16_t timeout, uint16_t iteration, uint16_t discriminator, uint8_t option, - Callback::Callback * callback, + chip::Callback::Callback * callback, bool readVIDPIDAttributes) { mSetupPayload = SetupPayload(); @@ -520,8 +522,8 @@ CHIP_ERROR DeviceController::OpenCommissioningWindowInternal() chip::Controller::AdministratorCommissioningCluster cluster; cluster.Associate(device, kAdministratorCommissioningClusterEndpoint); - Callback::Cancelable * successCallback = mOpenPairingSuccessCallback.Cancel(); - Callback::Cancelable * failureCallback = mOpenPairingFailureCallback.Cancel(); + chip::Callback::Cancelable * successCallback = mOpenPairingSuccessCallback.Cancel(); + chip::Callback::Cancelable * failureCallback = mOpenPairingFailureCallback.Cancel(); if (mCommissioningWindowOption != CommissioningWindowOption::kOriginalSetupCode) { @@ -563,8 +565,8 @@ CHIP_ERROR DeviceController::OpenCommissioningWindowInternal() CHIP_ERROR DeviceController::CreateBindingWithCallback(chip::NodeId deviceId, chip::EndpointId deviceEndpointId, chip::NodeId bindingNodeId, chip::GroupId bindingGroupId, chip::EndpointId bindingEndpointId, chip::ClusterId bindingClusterId, - Callback::Cancelable * onSuccessCallback, - Callback::Cancelable * onFailureCallback) + chip::Callback::Cancelable * onSuccessCallback, + chip::Callback::Cancelable * onFailureCallback) { PeerId peerId; peerId.SetNodeId(deviceId); @@ -781,8 +783,8 @@ CHIP_ERROR DeviceCommissioner::GetDeviceBeingCommissioned(NodeId deviceId, Commi return CHIP_NO_ERROR; } -CHIP_ERROR DeviceCommissioner::GetConnectedDevice(NodeId deviceId, Callback::Callback * onConnection, - Callback::Callback * onFailure) +CHIP_ERROR DeviceCommissioner::GetConnectedDevice(NodeId deviceId, chip::Callback::Callback * onConnection, + chip::Callback::Callback * onFailure) { return DeviceController::GetConnectedDevice(deviceId, onConnection, onFailure); } @@ -1054,8 +1056,8 @@ CHIP_ERROR DeviceCommissioner::SendCertificateChainRequestCommand(DeviceProxy * chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, 0); - Callback::Cancelable * successCallback = mCertificateChainResponseCallback.Cancel(); - Callback::Cancelable * failureCallback = mOnCertificateChainFailureCallback.Cancel(); + chip::Callback::Cancelable * successCallback = mCertificateChainResponseCallback.Cancel(); + chip::Callback::Cancelable * failureCallback = mOnCertificateChainFailureCallback.Cancel(); ReturnErrorOnFailure(cluster.CertificateChainRequest(successCallback, failureCallback, certificateType)); return CHIP_NO_ERROR; @@ -1092,8 +1094,8 @@ CHIP_ERROR DeviceCommissioner::SendAttestationRequestCommand(DeviceProxy * devic chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, 0); - Callback::Cancelable * successCallback = mAttestationResponseCallback.Cancel(); - Callback::Cancelable * failureCallback = mOnAttestationFailureCallback.Cancel(); + chip::Callback::Cancelable * successCallback = mAttestationResponseCallback.Cancel(); + chip::Callback::Cancelable * failureCallback = mOnAttestationFailureCallback.Cancel(); ReturnErrorOnFailure(cluster.AttestationRequest(successCallback, failureCallback, attestationNonce)); ChipLogDetail(Controller, "Sent Attestation request, waiting for the Attestation Information"); @@ -1182,8 +1184,8 @@ CHIP_ERROR DeviceCommissioner::SendOperationalCertificateSigningRequestCommand(D chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, 0); - Callback::Cancelable * successCallback = mOpCSRResponseCallback.Cancel(); - Callback::Cancelable * failureCallback = mOnCSRFailureCallback.Cancel(); + chip::Callback::Cancelable * successCallback = mOpCSRResponseCallback.Cancel(); + chip::Callback::Cancelable * failureCallback = mOnCSRFailureCallback.Cancel(); ReturnErrorOnFailure(cluster.OpCSRRequest(successCallback, failureCallback, csrNonce)); ChipLogDetail(Controller, "Sent OpCSR request, waiting for the CSR"); @@ -1281,8 +1283,8 @@ CHIP_ERROR DeviceCommissioner::SendOperationalCertificate(DeviceProxy * device, chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, 0); - Callback::Cancelable * successCallback = mNOCResponseCallback.Cancel(); - Callback::Cancelable * failureCallback = mOnCertFailureCallback.Cancel(); + chip::Callback::Cancelable * successCallback = mNOCResponseCallback.Cancel(); + chip::Callback::Cancelable * failureCallback = mOnCertFailureCallback.Cancel(); ReturnErrorOnFailure(cluster.AddNOC(successCallback, failureCallback, nocCertBuf, icaCertBuf, ipk, adminSubject, mVendorId)); @@ -1368,8 +1370,8 @@ CHIP_ERROR DeviceCommissioner::SendTrustedRootCertificate(DeviceProxy * device, chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, 0); - Callback::Cancelable * successCallback = mRootCertResponseCallback.Cancel(); - Callback::Cancelable * failureCallback = mOnRootCertFailureCallback.Cancel(); + chip::Callback::Cancelable * successCallback = mRootCertResponseCallback.Cancel(); + chip::Callback::Cancelable * failureCallback = mOnRootCertFailureCallback.Cancel(); ReturnErrorOnFailure(cluster.AddTrustedRootCertificate(successCallback, failureCallback, rcac)); @@ -1617,54 +1619,6 @@ void DeviceCommissioner::SetupCluster(ClusterBase & base, DeviceProxy * proxy, E base.SetCommandTimeout(timeout); } -void DescriptorClusterPartsCallback(void * context, const chip::app::DataModel::DecodableList & data) -{ - DeviceCommissioner * commissioner = static_cast(context); - EndpointParts parts; - auto iter = data.begin(); - while (iter.Next() && parts.numEndpoints < parts.kMaxEndpoints) - { - parts.endpoints[parts.numEndpoints++] = iter.GetValue(); - } - CommissioningDelegate::CommissioningReport report; - report.Set(parts); - commissioner->CommissioningStageComplete(iter.GetStatus(), report); -} - -void DescriptorClusterServerCallback(void * context, const chip::app::DataModel::DecodableList & data) -{ - DeviceCommissioner * commissioner = static_cast(context); - - bool hasGeneralCommissioning = false; - bool hasNetworkCommissioning = false; - bool hasBasic = false; - bool hasOperationalCredentials = false; - - auto iter = data.begin(); - while (iter.Next()) - { - switch (iter.GetValue()) - { - case app::Clusters::GeneralCommissioning::Id: - hasGeneralCommissioning = true; - break; - case app::Clusters::NetworkCommissioning::Id: - hasNetworkCommissioning = true; - break; - case app::Clusters::Basic::Id: - hasBasic = true; - break; - case app::Clusters::OperationalCredentials::Id: - hasOperationalCredentials = true; - break; - } - } - bool isCommissionable = hasGeneralCommissioning && hasBasic && hasOperationalCredentials; - CommissioningDelegate::CommissioningReport report; - report.Set(EndpointCommissioningInfo(isCommissionable, hasNetworkCommissioning)); - commissioner->CommissioningStageComplete(iter.GetStatus(), report); -} - void BasicVendorCallback(void * context, VendorId vendorId) { DeviceCommissioner * commissioner = static_cast(context); @@ -1688,13 +1642,6 @@ void BasicSoftwareCallback(void * context, uint32_t softwareVersion) report.Set(softwareVersion); commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report); } -void OnFeatureMapSuccess(void * context, uint32_t value) -{ - DeviceCommissioner * commissioner = static_cast(context); - CommissioningDelegate::CommissioningReport report; - report.Set(value); - commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report); -} void AttributeReadFailure(void * context, CHIP_ERROR status) { @@ -1702,6 +1649,43 @@ void AttributeReadFailure(void * context, CHIP_ERROR status) commissioner->CommissioningStageComplete(status); } +void DeviceCommissioner::OnDone() { + NetworkClusters clusters; + + CHIP_ERROR err = mAttributeCache->ForEachAttribute(app::Clusters::NetworkCommissioning::Id, [this, &clusters](const app::ConcreteAttributePath & path) { + if (path.mAttributeId != app::Clusters::NetworkCommissioning::Attributes::FeatureMap::Id) { + return CHIP_NO_ERROR; + } + TLV::TLVReader reader; + if (this->mAttributeCache->Get(path, reader) == CHIP_NO_ERROR) { + uint32_t flags = 0; + BitFlags features; + if (app::DataModel::Decode(reader, flags) == CHIP_NO_ERROR) { + features.SetRaw(flags); + if (features.Has(app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kWiFiNetworkInterface)) { + clusters.wifi = path.mEndpointId; + } else if (features.Has(app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kThreadNetworkInterface)) { + clusters.thread = path.mEndpointId; + } else if (features.Has(app::Clusters::NetworkCommissioning::NetworkCommissioningFeature::kEthernetNetworkInterface)) { + clusters.eth = path.mEndpointId; + } + else { + // TODO: Gross workaroud for the empty feature map on all clusters. Remove. + clusters.thread = path.mEndpointId; + } + } + } + return CHIP_NO_ERROR; + }); + + if (err != CHIP_NO_ERROR) { + ChipLogError(Controller, "Error parsing Network commissioning features"); + } + CommissioningDelegate::CommissioningReport report; + report.Set(clusters); + CommissioningStageComplete(err, report); +} + void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, CommissioningStage step, CommissioningParameters & params, CommissioningDelegate * delegate, EndpointId endpoint, Optional timeout) @@ -1744,21 +1728,26 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio AttributeReadFailure); } break; - - case CommissioningStage::kGetPartsList: { - ChipLogProgress(Controller, "Reading descriptor cluster parts list"); - DescriptorCluster desc; - SetupCluster(desc, proxy, endpoint, timeout); - desc.ReadAttribute(this, DescriptorClusterPartsCallback, - AttributeReadFailure); - } - break; - case CommissioningStage::kCheckEndpointIsCommissionable: { - ChipLogProgress(Controller, "Reading descriptor cluster server list for endpoint %u", endpoint); - DescriptorCluster desc; - SetupCluster(desc, proxy, endpoint, timeout); - desc.ReadAttribute(this, DescriptorClusterServerCallback, - AttributeReadFailure); + case CommissioningStage::kGetNetworkTechnology: { + ChipLogProgress(Controller, "Sending request for network cluster feature map"); + app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); + app::ReadPrepareParams readParams(proxy->GetSecureSession().Value()); + app::AttributePathParams paramList[1]; + paramList[0] = app::AttributePathParams(endpoint, app::Clusters::NetworkCommissioning::Id, app::Clusters::NetworkCommissioning::Attributes::FeatureMap::Id); + readParams.mpAttributePathParamsList = paramList; + readParams.mAttributePathParamsListSize = 1; + if (timeout.HasValue()) { + readParams.mTimeout = timeout.Value(); + } + mAttributeCache = Platform::MakeUnique(*this); + mReadClient = chip::Platform::MakeUnique(engine, proxy->GetExchangeManager(), mAttributeCache->GetBufferedCallback(), app::ReadClient::InteractionType::Read); + CHIP_ERROR err = mReadClient->SendRequest(readParams); + if (err != CHIP_NO_ERROR) { + ChipLogError(Controller, "Failed to send read request for networking clusters"); + CommissioningStageComplete(err); + return; + } + return; } break; case CommissioningStage::kArmFailsafe: { @@ -1768,15 +1757,6 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio genCom.ArmFailSafe(mSuccess.Cancel(), mFailure.Cancel(), params.GetFailsafeTimerSeconds(), breadcrumb, kCommandTimeoutMs); } break; - case CommissioningStage::kGetNetworkTechnology: { - ChipLogProgress(Controller, "Sending request for network cluster feature map on endpoint %u", endpoint); - NetworkCommissioningCluster netCom; - // TODO: swap to given endpoint once that PR is merged - netCom.Associate(proxy, 0); - netCom.ReadAttribute(this, OnFeatureMapSuccess, - AttributeReadFailure); - } - break; case CommissioningStage::kConfigRegulatory: { // To set during config phase: // UTC time diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index b89a66ade8b0f8..07cfb97a26db4c 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -28,6 +28,7 @@ #pragma once +#include #include #include #include @@ -215,7 +216,7 @@ class DLL_EXPORT DeviceController : public SessionRecoveryDelegate, * callback. If it fails to establish the connection, it calls `onError` callback. */ virtual CHIP_ERROR GetConnectedDevice(NodeId deviceId, Callback::Callback * onConnection, - Callback::Callback * onFailure) + chip::Callback::Callback * onFailure) { VerifyOrReturnError(mState == State::Initialized && mFabricInfo != nullptr, CHIP_ERROR_INCORRECT_STATE); return mCASESessionManager->FindOrEstablishSession(mFabricInfo->GetPeerIdForNode(deviceId), onConnection, onFailure); @@ -452,7 +453,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable public Protocols::UserDirectedCommissioning::InstanceNameResolver, #endif - public SessionEstablishmentDelegate + public SessionEstablishmentDelegate, public app::AttributeCache::Callback { public: DeviceCommissioner(); @@ -553,8 +554,8 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, CHIP_ERROR GetDeviceBeingCommissioned(NodeId deviceId, CommissioneeDeviceProxy ** device); - CHIP_ERROR GetConnectedDevice(NodeId deviceId, Callback::Callback * onConnection, - Callback::Callback * onFailure) override; + CHIP_ERROR GetConnectedDevice(NodeId deviceId, chip::Callback::Callback * onConnection, + chip::Callback::Callback * onFailure) override; /** * @brief @@ -682,6 +683,9 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, void RegisterPairingDelegate(DevicePairingDelegate * pairingDelegate) { mPairingDelegate = pairingDelegate; } + // ReadClient::Callback impl + void OnDone() override; + private: DevicePairingDelegate * mPairingDelegate; @@ -813,31 +817,34 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, void ReleaseCommissioneeDevice(CommissioneeDeviceProxy * device); // Cluster callbacks for advancing commissioning flows - Callback::Callback mSuccess; - Callback::Callback mFailure; + chip::Callback::Callback mSuccess; + chip::Callback::Callback mFailure; static CHIP_ERROR ConvertFromNodeOperationalCertStatus(uint8_t err); - Callback::Callback mCertificateChainResponseCallback; - Callback::Callback mAttestationResponseCallback; - Callback::Callback mOpCSRResponseCallback; - Callback::Callback mNOCResponseCallback; - Callback::Callback mRootCertResponseCallback; - Callback::Callback mOnCertificateChainFailureCallback; - Callback::Callback mOnAttestationFailureCallback; - Callback::Callback mOnCSRFailureCallback; - Callback::Callback mOnCertFailureCallback; - Callback::Callback mOnRootCertFailureCallback; + chip::Callback::Callback mCertificateChainResponseCallback; + chip::Callback::Callback mAttestationResponseCallback; + chip::Callback::Callback mOpCSRResponseCallback; + chip::Callback::Callback mNOCResponseCallback; + chip::Callback::Callback mRootCertResponseCallback; + chip::Callback::Callback mOnCertificateChainFailureCallback; + chip::Callback::Callback mOnAttestationFailureCallback; + chip::Callback::Callback mOnCSRFailureCallback; + chip::Callback::Callback mOnCertFailureCallback; + chip::Callback::Callback mOnRootCertFailureCallback; - Callback::Callback mOnDeviceConnectedCallback; - Callback::Callback mOnDeviceConnectionFailureCallback; + chip::Callback::Callback mOnDeviceConnectedCallback; + chip::Callback::Callback mOnDeviceConnectionFailureCallback; - Callback::Callback mDeviceAttestationInformationVerificationCallback; + chip::Callback::Callback mDeviceAttestationInformationVerificationCallback; - Callback::Callback mDeviceNOCChainCallback; + chip::Callback::Callback mDeviceNOCChainCallback; SetUpCodePairer mSetUpCodePairer; AutoCommissioner mAutoCommissioner; CommissioningDelegate * mCommissioningDelegate = nullptr; + + Platform::UniquePtr mAttributeCache; + Platform::UniquePtr mReadClient; }; } // namespace Controller diff --git a/src/controller/CommissioningDelegate.h b/src/controller/CommissioningDelegate.h index 9e8203bcdaaa43..de9f0f174b77c6 100644 --- a/src/controller/CommissioningDelegate.h +++ b/src/controller/CommissioningDelegate.h @@ -31,13 +31,11 @@ enum CommissioningStage : uint8_t kReadVendorId, kReadProductId, kReadSoftwareVersion, - kGetPartsList, - kCheckEndpointIsCommissionable, + kGetNetworkTechnology, kArmFailsafe, // kConfigTime, // NOT YET IMPLEMENTED // kConfigTimeZone, // NOT YET IMPLEMENTED // kConfigDST, // NOT YET IMPLEMENTED - kGetNetworkTechnology, kConfigRegulatory, kSendPAICertificateRequest, kSendDACCertificateRequest, @@ -239,22 +237,6 @@ struct OperationalNodeFoundData OperationalDeviceProxy * operationalProxy; }; -struct EndpointParts -{ - EndpointParts() : numEndpoints(0) {} - // TODO: I don't think this is specified anywhere in the spec - // Is 10 reasonable? This is just to find the network commissioning clusters - static constexpr size_t kMaxEndpoints = 10; - EndpointId endpoints[kMaxEndpoints]; - size_t numEndpoints; -}; -struct EndpointCommissioningInfo -{ - EndpointCommissioningInfo(bool commissionable, bool network) : isCommissionable(commissionable), hasNetworkCluster(network) {} - bool isCommissionable = false; - bool hasNetworkCluster = false; -}; - struct BasicVendor { BasicVendor(VendorId id) : vendorId(id) {} @@ -272,10 +254,12 @@ struct BasicSoftware BasicSoftware(uint32_t version) : softwareVersion(version) {} uint32_t softwareVersion; }; -struct FeatureMap + +struct NetworkClusters { - FeatureMap(uint32_t featureBitmap) : features(featureBitmap) {} - uint32_t features; + EndpointId wifi = kInvalidEndpointId; + EndpointId thread = kInvalidEndpointId; + EndpointId eth = kInvalidEndpointId; }; class CommissioningDelegate @@ -283,8 +267,8 @@ class CommissioningDelegate public: virtual ~CommissioningDelegate(){}; struct CommissioningReport - : Variant + : Variant { CommissioningReport() : stageCompleted(CommissioningStage::kError) {} CommissioningStage stageCompleted;