@@ -1611,6 +1611,27 @@ void OnBasicFailure(void * context, CHIP_ERROR error)
1611
1611
commissioner->CommissioningStageComplete (error);
1612
1612
}
1613
1613
1614
+ static void NonConcurrentTimeout (void * context, CHIP_ERROR error)
1615
+ {
1616
+ if (error == CHIP_ERROR_TIMEOUT)
1617
+ {
1618
+ ChipLogProgress (Controller, " Non-concurrent mode: Expected NetworkResponse Timeout, do nothing" );
1619
+ }
1620
+ else
1621
+ {
1622
+ ChipLogProgress (Controller, " Non-concurrent mode: Received failure response %" CHIP_ERROR_FORMAT, error.Format ());
1623
+ }
1624
+ }
1625
+
1626
+ static void NonConcurrentNetworkResponse (void * context,
1627
+ const NetworkCommissioning::Commands::ConnectNetworkResponse::DecodableType & data)
1628
+ {
1629
+ // In Non Concurrent mode the commissioning network should have been shut down and not sent the
1630
+ // ConnectNetworkResponse. In case it does send it this handles the message
1631
+ ChipLogError (Controller, " Non-concurrent Mode : Received Unexpected ConnectNetwork response, ignoring. Status=%u" ,
1632
+ to_underlying (data.networkingStatus ));
1633
+ }
1634
+
1614
1635
void DeviceCommissioner::CleanupCommissioning (DeviceProxy * proxy, NodeId nodeId, const CompletionStatus & completionStatus)
1615
1636
{
1616
1637
commissioningCompletionStatus = completionStatus;
@@ -2111,6 +2132,16 @@ void DeviceCommissioner::ParseCommissioningInfo2()
2111
2132
ReadCommissioningInfo2 info;
2112
2133
CHIP_ERROR return_err = CHIP_NO_ERROR;
2113
2134
2135
+ using namespace chip ::app::Clusters::GeneralCommissioning::Attributes;
2136
+ CHIP_ERROR err =
2137
+ mAttributeCache ->Get <SupportsConcurrentConnection::TypeInfo>(kRootEndpointId , info.supportsConcurrentConnection );
2138
+ if (err != CHIP_NO_ERROR)
2139
+ {
2140
+ // May not be present so don't return the error code, non fatal, default concurrent
2141
+ ChipLogError (Controller, " Failed to read SupportsConcurrentConnection: %" CHIP_ERROR_FORMAT, err.Format ());
2142
+ info.supportsConcurrentConnection = true ;
2143
+ }
2144
+
2114
2145
return_err = ParseFabrics (info);
2115
2146
2116
2147
if (return_err == CHIP_NO_ERROR)
@@ -2206,6 +2237,8 @@ CHIP_ERROR DeviceCommissioner::ParseICDInfo(ReadCommissioningInfo2 & info)
2206
2237
}
2207
2238
else if (err == CHIP_ERROR_KEY_NOT_FOUND)
2208
2239
{
2240
+ // This key is optional so not an error
2241
+ err = CHIP_NO_ERROR;
2209
2242
info.isIcd = false ;
2210
2243
}
2211
2244
else if (err == CHIP_ERROR_IM_STATUS_CODE_RECEIVED)
@@ -2440,6 +2473,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio
2440
2473
case CommissioningStage::kReadCommissioningInfo : {
2441
2474
ChipLogProgress (Controller, " Sending read request for commissioning information" );
2442
2475
// NOTE: this array cannot have more than 9 entries, since the spec mandates that server only needs to support 9
2476
+ // See R1.1, 2.11.2 Interaction Model Limits
2443
2477
app::AttributePathParams readPaths[9 ];
2444
2478
// Read all the feature maps for all the networking clusters on any endpoint to determine what is supported
2445
2479
readPaths[0 ] = app::AttributePathParams (app::Clusters::NetworkCommissioning::Id,
@@ -2471,7 +2505,14 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio
2471
2505
case CommissioningStage::kReadCommissioningInfo2 : {
2472
2506
size_t numberOfAttributes = 0 ;
2473
2507
// This is done in a separate step since we've already used up all the available read paths in the previous read step
2474
- app::AttributePathParams readPaths[9 ];
2508
+ // NOTE: this array cannot have more than 9 entries, since the spec mandates that server only needs to support 9
2509
+ // See R1.1, 2.11.2 Interaction Model Limits
2510
+ app::AttributePathParams readPaths[3 ];
2511
+
2512
+ // Mandatory attribute
2513
+ readPaths[numberOfAttributes++] =
2514
+ app::AttributePathParams (endpoint, app::Clusters::GeneralCommissioning::Id,
2515
+ app::Clusters::GeneralCommissioning::Attributes::SupportsConcurrentConnection::Id);
2475
2516
2476
2517
// Read the current fabrics
2477
2518
if (params.GetCheckForMatchingFabric ())
@@ -2486,18 +2527,6 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio
2486
2527
app::AttributePathParams (endpoint, IcdManagement::Id, IcdManagement::Attributes::FeatureMap::Id);
2487
2528
}
2488
2529
2489
- // Current implementation makes sense when we only have a few attributes to read with conditions. Should revisit this if we
2490
- // are adding more attributes here.
2491
-
2492
- if (numberOfAttributes == 0 )
2493
- {
2494
- // We don't actually want to do this step, so just bypass it
2495
- ChipLogProgress (Controller, " kReadCommissioningInfo2 step called without parameter set, skipping" );
2496
- CommissioningStageComplete (CHIP_NO_ERROR);
2497
- return ;
2498
- }
2499
-
2500
- ChipLogProgress (Controller, " Sending request for commissioning information -- Part 2" );
2501
2530
SendCommissioningReadRequest (proxy, timeout, readPaths, numberOfAttributes);
2502
2531
}
2503
2532
break ;
@@ -2918,7 +2947,31 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio
2918
2947
NetworkCommissioning::Commands::ConnectNetwork::Type request;
2919
2948
request.networkID = params.GetWiFiCredentials ().Value ().ssid ;
2920
2949
request.breadcrumb .Emplace (breadcrumb);
2921
- CHIP_ERROR err = SendCommand (proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout);
2950
+
2951
+ CHIP_ERROR err = CHIP_NO_ERROR;
2952
+ GeneralCommissioning::Attributes::SupportsConcurrentConnection::TypeInfo::Type supportsConcurrentConnection;
2953
+ supportsConcurrentConnection = params.GetSupportsConcurrentConnection ().Value ();
2954
+ ChipLogProgress (Controller, " SendCommand kWiFiNetworkEnable, supportsConcurrentConnection=%d" ,
2955
+ supportsConcurrentConnection);
2956
+ if (supportsConcurrentConnection)
2957
+ {
2958
+ err = SendCommand (proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout);
2959
+ }
2960
+ else
2961
+ {
2962
+ // Concurrent Connections not allowed. Send the ConnectNetwork command but do not wait for the
2963
+ // ConnectNetworkResponse on the Commissioning network as it will not be present. Log the expected timeout
2964
+ // and run what would have been in the onConnectNetworkResponse callback.
2965
+ err = SendCommand (proxy, request, NonConcurrentNetworkResponse, NonConcurrentTimeout, endpoint, NullOptional);
2966
+ if (err == CHIP_NO_ERROR)
2967
+ {
2968
+ // As there will be no ConnectNetworkResponse, it is an implicit kSuccess so a default report is fine
2969
+ CommissioningDelegate::CommissioningReport report;
2970
+ CommissioningStageComplete (CHIP_NO_ERROR, report);
2971
+ return ;
2972
+ }
2973
+ }
2974
+
2922
2975
if (err != CHIP_NO_ERROR)
2923
2976
{
2924
2977
// We won't get any async callbacks here, so just complete our stage.
0 commit comments