tv-casting-app updated APIs.md docs with new v1.3 Matter APIs (#34093)
* tv-casting-app updated APIs.md docs with new v1.3 Matter APIs
* Fixing spelling error
* Addressed comments by sharadb-amazon
* Addressed comments by sharadb-amazon2
diff --git a/examples/tv-casting-app/APIs.md b/examples/tv-casting-app/APIs.md
index 76af45a..75c63eb 100644
--- a/examples/tv-casting-app/APIs.md
+++ b/examples/tv-casting-app/APIs.md
@@ -158,6 +158,16 @@
the Matter specification's "Onboarding Payload" section for more details on
commissioning data.
+ For the optional `CastingPlayer` / Commissioner-Generated Passcode User
+ Directed Commissioning (UDC) feature, the Commissioning `DataProvider` needs
+ to be updated during the commissioning process. In this scenario, the
+ `CastingPlayer` generates a Passcode and displays it for the user. The user
+ enters the Passcode on the UX of the Casting Client which should update its
+ Commissioning `DataProvider`. This allows the Matter Casting Library to run
+ commissioning with the `CastingPlayer` using a PAKE verifier based on the
+ user-entered passcode. See the Matter specification’s UDC section for more
+ information on the Commissioner-Generated Passcode feature.
+
On Linux, define a function `InitCommissionableDataProvider` to initialize a
`LinuxCommissionableDataProvider` that can provide the required values to
the `CastingApp`.
@@ -185,33 +195,95 @@
}
```
+ On Linux, if using the `CastingPlayer` / Commissioner-Generated Passcode UDC
+ feature, set up a new `LinuxCommissionableDataProvider` when called back on
+ the `CommissionerDeclarationCallback` during the
+ [VerifyOrEstablishConnection()](#connect-to-a-casting-player) API call
+ (described later). The `CastingPlayer` generated passcode (as entered by the
+ user on the Casting Client UX) should be set in this
+ `LinuxCommissionableDataProvider` which should then be passed to the
+ CastingApp using the `UpdateCommissionableDataProvider` API.
+
+ ```c
+ LinuxDeviceOptions::GetInstance().payload.setUpPINCode = userEnteredPasscode;
+ LinuxCommissionableDataProvider gCommissionableDataProvider;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ err = InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance());
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer,
+ "CommandHandler() setcommissionerpasscode InitCommissionableDataProvider() err %" CHIP_ERROR_FORMAT, err.Format());
+ return err;
+ }
+ err = matter::casting::core::CastingApp::GetInstance()->UpdateCommissionableDataProvider(&gCommissionableDataProvider);
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer,
+ "CommandHandler() setcommissionerpasscode InitCommissionableDataProvider() err %" CHIP_ERROR_FORMAT, err.Format());
+ return err;
+ }
+ ```
+
On Android, define a `commissioningDataProvider` that can provide the
- required values to the `CastingApp`.
+ required values to the `CastingApp`. If using the `CastingPlayer` /
+ Commissioner-Generated Passcode UDC feature, the Casting Client needs to
+ update this `commissioningDataProvider` during the
+ [verifyOrEstablishConnection()](#connect-to-a-casting-player) API call
+ (described later). In the example below,
+ `updateCommissionableDataSetupPasscode` updates the CommissionableData with
+ the `CastingPlayer` generated passcode entered by the user on the Casting
+ Client UX.
```java
- private static final DataProvider<CommissionableData> commissionableDataProvider =
- new DataProvider<CommissionableData>() {
+ public static class CommissionableDataProvider implements DataProvider<CommissionableData> {
+ CommissionableData commissionableData =
+ // Dummy values for commissioning demonstration only. These are hard coded in the example tv-app:
+ // connectedhomeip/examples/tv-app/tv-common/src/AppTv.cpp
+ private static final long DUMMY_SETUP_PASSCODE = 20202021;
+ private static final int DUMMY_DISCRIMINATOR = 3874;
+
+ new CommissionableData(DUMMY_SETUP_PASSCODE, DUMMY_DISCRIMINATOR);
+
@Override
public CommissionableData get() {
- // dummy values for demonstration only
- return new CommissionableData(20202021, 3874);
+ return commissionableData;
+ }
+
+ // If using the alternate CastingPlayer / Commissioner-Generated Passcode UDC feature:
+ public void updateCommissionableDataSetupPasscode(long setupPasscode, int discriminator) {
+ commissionableData.setSetupPasscode(setupPasscode);
+ commissionableData.setDiscriminator(discriminator);
}
};
```
On iOS, add a `func commissioningDataProvider` to the
`MCAppParametersDataSource` class defined above, that can provide the
- required values to the `MCCastingApp`.
+ required values to the `MCCastingApp`. If using the `CastingPlayer` /
+ Commissioner-Generated Passcode UDC feature, the Casting Client needs to
+ update this `commissioningDataProvider` during the
+ [VerifyOrEstablishConnection()](#connect-to-a-casting-player) API call
+ (described later). In the example below, the `update` function updates the
+ CommissionableData with the `CastingPlayer` generated passcode entered by
+ the user on the Casting Client UX.
```swift
+ // Dummy values for demonstration only.
+ private var commissionableData: MCCommissionableData = MCCommissionableData(
+ passcode: 20202021,
+ discriminator: 3874,
+ spake2pIterationCount: 1000,
+ spake2pVerifier: nil,
+ spake2pSalt: nil
+ )
+
func castingAppDidReceiveRequestForCommissionableData(_ sender: Any) -> MCCommissionableData {
- // dummy values for demonstration only
- return MCCommissionableData(
- passcode: 20202021,
- discriminator: 3874,
- spake2pIterationCount: 1000,
- spake2pVerifier: nil,
- spake2pSalt: nil)
+ return commissionableData
+ }
+
+ // If using the alternate CastingPlayer / Commissioner-Generated Passcode UDC feature:
+ func update(_ newCommissionableData: MCCommissionableData) {
+ self.commissionableData = newCommissionableData
}
```
@@ -703,9 +775,42 @@
[Discovery](#discover-casting-players) contains information such as
`deviceName`, `vendorId`, `productId`, etc. which can help the user pick the
right `CastingPlayer`. A Casting Client can attempt to connect to the
-`selectedCastingPlayer` using Matter User Directed Commissioning (UDC). The
-Matter TV Casting library locally caches information required to reconnect to a
-`CastingPlayer`, once the Casting client has been commissioned by it. After
+`selectedCastingPlayer` using Matter User Directed Commissioning (UDC), where
+the Casting Client generates the passcode. Alternately, a Casting Client can
+attempt to connect to a `CastingPlayer`, using the `CastingPlayer`/
+Commissioner-Generated Passcode UDC feature, if the
+`supportsCommissionerGeneratedPasscode` flag on the `selectedCastingPlayer` is
+set to `true`.
+
+For a Casting Client to connect to a `CastingPlayer` using the optional
+`CastingPlayer` / Commissioner-Generated Passcode UDC feature, the Casting
+Client may specify optional parameters in the `VerifyOrEstablishConnection`
+function call and then respond to the CastingPlayer's CommissionerDeclaration
+message as follows:
+
+1. In `VerifyOrEstablishConnection` the Casting Client should set the UDC
+ IdentificationDeclaration `CommissionerPasscode` field to true and provide a
+ `CommissionerDeclarationCallback` in the `ConnectionCallbacks` parameter to
+ handle the CastingPlayer's CommissionerDeclaration message during
+ commissioning.
+2. Upon receiving the CastingPlayer’s CommissionerDeclaration message with
+ PasscodeDialogDisplayed set to true, the Casting Client should prompt the
+ user to input the Passcode displayed on the `CastingPlayer` UX. If the user
+ declines to enter the Passcode, the Casting Client should call
+ `StopConnecting` to alert the `CastingPlayer` that the commissioning attempt
+ was canceled.
+3. The Casting Client should then update the passcode to be used for
+ commissioning session to the user-entered Passcode. Refer to how to set up
+ the `commissioningDataProvider` in
+ [Initialize the Casting Client](#initialize-the-casting-client) section
+ above.
+4. Finally, the Casting Client should call `ContinueConnecting` to send a second
+ IdentificationDeclaration message to the `CastingPlayer` with
+ `CommissionerPasscodeReady` in `IdentificationDeclarationOptions` set to
+ true.
+
+The Matter TV Casting library locally caches information required to reconnect
+to a `CastingPlayer`, once the Casting client has been commissioned by it. After
that, the Casting client is able to skip the full UDC process by establishing
CASE with the `CastingPlayer` directly. Once connected, the `CastingPlayer`
object will contain the list of available Endpoints on that `CastingPlayer`.
@@ -718,7 +823,11 @@
Endpoint, in cases where it is not available in the Casting client's cache.
On Linux, the Casting Client can connect to a `CastingPlayer` by successfully
-calling `VerifyOrEstablishConnection` on it.
+calling `VerifyOrEstablishConnection` on it. Alternately, the Casting Client can
+connect to a `CastingPlayer` using the `CastingPlayer` / Commissioner-Generated
+Passcode UDC feature, by successfully calling `VerifyOrEstablishConnection`,
+updating the commissioning passcode and then calling `ContinueConnecting` on the
+`CastingPlayer`.
```c
// VendorId of the Endpoint on the CastingPlayer that the CastingApp desires to interact with after connection
@@ -733,59 +842,166 @@
}
}
-...
+// If using the alternate CastingPlayer / Commissioner-Generated Passcode UDC feature:
+// Define a callback to handle CastingPlayer’s CommissionerDeclaration messages.
+void CommissionerDeclarationCallback(const chip::Transport::PeerAddress & source,
+ chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd)
+{
+ ChipLogProgress(AppServer,
+ "simple-app-helper.cpp::CommissionerDeclarationCallback() called with CommissionerDeclaration message:");
+ if (cd.GetCommissionerPasscode())
+ {
+ // A Passcode is now displayed for the user by the CastingPlayer. Prompt the user to enter the Passcode.
+ ...
+
+ // Update the commissioning session's passcode with the user-entered Passcode
+ LinuxDeviceOptions::GetInstance().payload.setUpPINCode = userEnteredPasscode;
+ LinuxCommissionableDataProvider gCommissionableDataProvider;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ err = InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance());
+ err = matter::casting::core::CastingApp::GetInstance()->UpdateCommissionableDataProvider(&gCommissionableDataProvider);
+
+ // Call continueConnecting to complete commissioning.
+ err = targetCastingPlayer->ContinueConnecting();
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer, "CommandHandler() setcommissionerpasscode ContinueConnecting() err %" CHIP_ERROR_FORMAT,
+ err.Format());
+ // Since continueConnecting() failed, Attempt to cancel the connection attempt with
+ // the CastingPlayer/Commissioner by calling StopConnecting().
+ err = targetCastingPlayer->StopConnecting();
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer, "CommandHandler() setcommissionerpasscode, ContinueConnecting() failed and then StopConnecting failed due to err %" CHIP_ERROR_FORMAT, err.Format());
+ }
+ }
+ }
+}
+
+// Specify the TargetApp that the client wants to interact with after commissioning. If this value is passed in,
+// VerifyOrEstablishConnection() will force UDC, in case the desired TargetApp is not found in the on-device
+// CastingStore
+matter::casting::core::IdentificationDeclarationOptions idOptions;
+chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo;
+targetAppInfo.vendorId = kDesiredEndpointVendorId;
+CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo);
+
+matter::casting::core::ConnectionCallbacks connectionCallbacks;
+connectionCallbacks.mOnConnectionComplete = ConnectionHandler;
+
+// If using the alternate CastingPlayer / Commissioner-Generated Passcode UDC feature:
+// Set the IdentificationDeclaration CommissionerPasscode flag to instruct the CastingPlayer /
+// Commissioner to use the Commissioner-generated Passcode for commissioning. Set the
+// CommissionerDeclarationCallback in ConnectionCallbacks.
+idOptions.mCommissionerPasscode = true;
+connectionCallbacks.mCommissionerDeclarationCallback = CommissionerDeclarationCallback;
+
// targetCastingPlayer is a discovered CastingPlayer
-matter::casting::core::EndpointFilter desiredEndpointFilter;
-desiredEndpointFilter.vendorId = kDesiredEndpointVendorId;
-targetCastingPlayer->VerifyOrEstablishConnection(ConnectionHandler,
+targetCastingPlayer->VerifyOrEstablishConnection(connectionCallbacks,
matter::casting::core::kCommissioningWindowTimeoutSec,
- desiredEndpointFilter);
+ idOptions);
...
```
On Android, the Casting Client may call `verifyOrEstablishConnection` on the
-`CastingPlayer` object it wants to connect to.
+`CastingPlayer` object it wants to connect to. Alternately, the Casting Client
+can connect to a `CastingPlayer`, using the `CastingPlayer` /
+Commissioner-Generated Passcode UDC feature by successfully calling
+`verifyOrEstablishConnection`, updating the commissioning passcode and then
+calling `continueConnecting` on the `CastingPlayer`.
```java
-private static final long MIN_CONNECTION_TIMEOUT_SEC = 3 * 60;
+private static final short MIN_CONNECTION_TIMEOUT_SEC = 3 * 60;
+private static final Integer DESIRED_TARGET_APP_VENDOR_ID = 65521;
-EndpointFilter desiredEndpointFilter = new EndpointFilter();
-desiredEndpointFilter.vendorId = DESIRED_ENDPOINT_VENDOR_ID;
+// Specify the TargetApp that the client wants to interact with after commissioning. If this value is passed in,
+// VerifyOrEstablishConnection() will force UDC, in case the desired TargetApp is not found in the on-device
+// CastingStore
+IdentificationDeclarationOptions idOptions = new IdentificationDeclarationOptions();
+TargetAppInfo targetAppInfo = new TargetAppInfo(DESIRED_TARGET_APP_VENDOR_ID);
+idOptions.addTargetAppInfo(targetAppInfo);
+
+// If using the alternate CastingPlayer / Commissioner-Generated Passcode UDC feature.
+// Set the IdentificationDeclaration CommissionerPasscode flag to instruct the CastingPlayer /
+// Commissioner to use the Commissioner-generated Passcode for commissioning.
+idOptions = new IdentificationDeclarationOptions(commissionerPasscode:true);
+idOptions.addTargetAppInfo(targetAppInfo);
+
+ConnectionCallbacks connectionCallbacks =
+ new ConnectionCallbacks(
+ new MatterCallback<Void>() {
+ @Override
+ public void handle(Void v) {
+ Log.i(
+ TAG,
+ "Successfully connected to CastingPlayer with deviceId: "
+ + targetCastingPlayer.getDeviceId());
+ getActivity()
+ .runOnUiThread(
+ () -> {
+ connectionFragmentStatusTextView.setText(
+ "Successfully connected to Casting Player with device name: "
+ + targetCastingPlayer.getDeviceName()
+ + "\n\n");
+ connectionFragmentNextButton.setEnabled(true);
+ });
+ }
+ },
+ new MatterCallback<MatterError>() {
+ @Override
+ public void handle(MatterError err) {
+ Log.e(TAG, "CastingPlayer connection failed: " + err);
+ getActivity()
+ .runOnUiThread(
+ () -> {
+ connectionFragmentStatusTextView.setText(
+ "Casting Player connection failed due to: " + err + "\n\n");
+ });
+ }
+ },
+ // If using the alternate CastingPlayer / Commissioner-Generated Passcode UDC feature.
+ // Define a callback to handle CastingPlayer’s CommissionerDeclaration messages.
+ // This can be null if using Casting Client / Commissionee generated passcode commissioning.
+ new MatterCallback<CommissionerDeclaration>() {
+ @Override
+ public void handle(CommissionerDeclaration cd) {
+ getActivity()
+ .runOnUiThread(
+ () -> {
+ connectionFragmentStatusTextView.setText(
+ "CommissionerDeclaration message received from Casting Player: \n\n");
+ if (cd.getCommissionerPasscode()) {
+
+ displayPasscodeInputDialog(getActivity());
+ ...
+
+ // Update the commissioning session's passcode with the user-entered Passcode
+ InitializationExample.commissionableDataProvider.updateCommissionableDataSetupPasscode(
+ passcodeLongValue, DEFAULT_DISCRIMINATOR_FOR_CGP_FLOW);
+
+ // Call continueConnecting to complete commissioning.
+ MatterError err = targetCastingPlayer.continueConnecting();
+ if (err.hasError()) {
+ ...
+ Log.e(
+ TAG,
+ "displayPasscodeInputDialog() continueConnecting() failed, calling stopConnecting() due to: "
+ + err);
+ // Since continueConnecting() failed, Attempt to cancel the connection attempt with
+ // the CastingPlayer/Commissioner by calling stopConnecting().
+ err = targetCastingPlayer.stopConnecting();
+ if (err.hasError()) {
+ Log.e(TAG, "displayPasscodeInputDialog() stopConnecting() failed due to: " + err);
+ }
+ }
+ }
+ });
+ }
+ }
+ );
MatterError err = targetCastingPlayer.verifyOrEstablishConnection(
- MIN_CONNECTION_TIMEOUT_SEC,
- desiredEndpointFilter,
- new MatterCallback<Void>() {
- @Override
- public void handle(Void v) {
- Log.i(
- TAG,
- "Connected to CastingPlayer with deviceId: "
- + targetCastingPlayer.getDeviceId());
- getActivity()
- .runOnUiThread(
- () -> {
- connectionFragmentStatusTextView.setText(
- "Connected to Casting Player with device name: "
- + targetCastingPlayer.getDeviceName()
- + "\n\n");
- connectionFragmentNextButton.setEnabled(true);
- });
- }
- },
- new MatterCallback<MatterError>() {
- @Override
- public void handle(MatterError err) {
- Log.e(TAG, "CastingPLayer connection failed: " + err);
- getActivity()
- .runOnUiThread(
- () -> {
- connectionFragmentStatusTextView.setText(
- "Casting Player connection failed due to: " + err + "\n\n");
- });
- }
- });
-
+ connectionCallbacks, MIN_CONNECTION_TIMEOUT_SEC, idOptions);
if (err.hasError())
{
getActivity()
@@ -799,7 +1015,11 @@
On iOS, the Casting Client may call `verifyOrEstablishConnection` on the
`MCCastingPlayer` object it wants to connect to and handle any `NSErrors` that
-may happen in the process.
+may happen in the process. Alternately, the Casting Client can connect to a
+`CastingPlayer` using the `CastingPlayer` / Commissioner-Generated Passcode UDC
+feature, by successfully calling `verifyOrEstablishConnection`, updating the
+commissioning passcode and then calling `continueConnecting` on the
+`CastingPlayer`.
```swift
// VendorId of the MCEndpoint on the MCCastingPlayer that the MCCastingApp desires to interact with after connection
@@ -810,21 +1030,111 @@
@Published var connectionStatus: String?;
func connect(selectedCastingPlayer: MCCastingPlayer?) {
- let desiredEndpointFilter: MCEndpointFilter = MCEndpointFilter()
- desiredEndpointFilter.vendorId = kDesiredEndpointVendorId
- selectedCastingPlayer?.verifyOrEstablishConnection(completionBlock: { err in
- self.Log.error("MCConnectionExampleViewModel connect() completed with \(err)")
- if(err == nil)
- {
- self.connectionSuccess = true
- self.connectionStatus = "Connected!"
+
+ let connectionCompleteCallback: (Swift.Error?) -> Void = { err in
+ self.Log.error("MCConnectionExampleViewModel connect() completed with: \(err)")
+ DispatchQueue.main.async {
+ if err == nil {
+ self.connectionSuccess = true
+ self.connectionStatus = "Successfully connected to Casting Player!"
+ } else {
+ self.connectionSuccess = false
+ self.connectionStatus = "Connection to Casting Player failed with: \(String(describing: err))"
+ }
}
- else
- {
- self.connectionSuccess = false
- self.connectionStatus = "Connection failed with \(String(describing: err))"
+ }
+
+ // If using the alternate CastingPlayer / Commissioner-Generated Passcode UDC feature.
+ // Define a callback to handle CastingPlayer’s CommissionerDeclaration messages.
+ let commissionerDeclarationCallback: (MCCommissionerDeclaration) -> Void = { commissionerDeclarationMessage in
+ DispatchQueue.main.async {
+ self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, recived a message form the MCCastingPlayer:\n\(commissionerDeclarationMessage)")
+ if commissionerDeclarationMessage.commissionerPasscode {
+ if let topViewController = self.getTopMostViewController() {
+ self.displayPasscodeInputDialog(on: topViewController, continueConnecting: { userEnteredPasscode in
+ self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, Continuing to connect with user entered MCCastingPlayer/Commissioner-Generated passcode: \(passcode)")
+
+ // Update the commissioning session's passcode with the user-entered Passcode
+ if let dataSource = initializationExample.getAppParametersDataSource() {
+ let newCommissionableData = MCCommissionableData(
+ passcode: UInt32(userEnteredPasscode) ?? 0,
+ discriminator: 0,
+ ...
+ )
+ dataSource.update(newCommissionableData)
+ ...
+ } else {
+ self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed, calling stopConnecting()")
+ self.connectionStatus = "Failed to update the MCAppParametersDataSource with the user entered passcode: \n\nRoute back and try again."
+ self.connectionSuccess = false
+ // Since we failed to update the passcode, attempt to cancel the connection attempt with
+ // the CastingPlayer/Commissioner.
+ let err = selectedCastingPlayer?.stopConnecting()
+ if err == nil {
+ self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed, then stopConnecting() succeeded")
+ } else {
+ self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed, then stopConnecting() failed due to: \(err)")
+ }
+ return
+ }
+
+ // Call continueConnecting to complete commissioning.
+ let errContinue = selectedCastingPlayer?.continueConnecting()
+ if errContinue == nil {
+ self.connectionStatus = "Continuing to connect with user entered passcode: \(userEnteredPasscode)"
+ } else {
+ self.connectionStatus = "Continue Connecting to Casting Player failed with: \(String(describing: errContinue)) \n\nRoute back and try again."
+ self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, MCCastingPlayer.continueConnecting() failed due to: \(errContinue)")
+ // Since continueConnecting() failed, Attempt to cancel the connection attempt with
+ // the CastingPlayer/Commissioner by calling stopConnecting().
+ let err = selectedCastingPlayer?.stopConnecting()
+ if err == nil {
+ self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, MCCastingPlayer.continueConnecting() failed, then stopConnecting() succeeded")
+ } else {
+ self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, MCCastingPlayer.continueConnecting() failed, then stopConnecting() failed due to: \(err)")
+ }
+ }
+ }, cancelConnecting: {
+ self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, Connection attempt cancelled by the user, calling MCCastingPlayer.stopConnecting()")
+ let err = selectedCastingPlayer?.stopConnecting()
+ ...
+ })
+ }
+ }
}
- }, desiredEndpointFilter: desiredEndpointFilter)
+ }
+
+ let identificationDeclarationOptions: MCIdentificationDeclarationOptions
+ let targetAppInfo: MCTargetAppInfo
+ let connectionCallbacks: MCConnectionCallbacks
+
+ // Specify the TargetApp that the client wants to interact with after commissioning. If this value is passed in,
+ // VerifyOrEstablishConnection() will force UDC, in case the desired TargetApp is not found in the on-device
+ // CastingStore
+ identificationDeclarationOptions = MCIdentificationDeclarationOptions()
+ targetAppInfo = MCTargetAppInfo(vendorId: kDesiredEndpointVendorId)
+ connectionCallbacks = MCConnectionCallbacks(
+ callbacks: connectionCompleteCallback,
+ commissionerDeclarationCallback: nil
+ )
+ identificationDeclarationOptions.addTargetAppInfo(targetAppInfo)
+
+ // If using the alternate CastingPlayer / Commissioner-Generated Passcode UDC feature.
+ // Set the IdentificationDeclaration CommissionerPasscode flag to instruct the CastingPlayer /
+ // Commissioner to use the Commissioner-generated Passcode for commissioning. Set the
+ // CommissionerDeclarationCallback in MCConnectionCallbacks.
+ identificationDeclarationOptions = MCIdentificationDeclarationOptions(commissionerPasscodeOnly: true)
+ targetAppInfo = MCTargetAppInfo(vendorId: kDesiredEndpointVendorId)
+ connectionCallbacks = MCConnectionCallbacks(
+ callbacks: connectionCompleteCallback,
+ commissionerDeclarationCallback: commissionerDeclarationCallback
+ )
+ identificationDeclarationOptions.addTargetAppInfo(targetAppInfo)
+
+ let err = selectedCastingPlayer?.verifyOrEstablishConnection(with: connectionCallbacks, identificationDeclarationOptions: identificationDeclarationOptions)
+ if err != nil {
+ self.Log.error("MCConnectionExampleViewModel connect(), MCCastingPlayer.verifyOrEstablishConnection() failed due to: \(err)")
+ }
}
```
@@ -864,26 +1174,22 @@
```java
private static final Integer SAMPLE_ENDPOINT_VID = 65521;
-private Endpoint selectFirstEndpointByVID()
-{
- Endpoint endpoint = null;
- if(selectedCastingPlayer != null)
- {
- List<Endpoint> endpoints = selectedCastingPlayer.getEndpoints();
- if (endpoints == null)
- {
- Log.e(TAG, "No Endpoints found on CastingPlayer");
- }
- else
- {
- endpoint = endpoints
- .stream()
- .filter(e -> SAMPLE_ENDPOINT_VID.equals(e.getVendorId()))
- .findFirst()
- .get();
- }
+public static Endpoint selectFirstEndpointByVID(CastingPlayer selectedCastingPlayer) {
+Endpoint endpoint = null;
+if (selectedCastingPlayer != null) {
+ List<Endpoint> endpoints = selectedCastingPlayer.getEndpoints();
+ if (endpoints == null) {
+ Log.e(TAG, "selectFirstEndpointByVID() No Endpoints found on CastingPlayer");
+ } else {
+ endpoint =
+ endpoints
+ .stream()
+ .filter(e -> SAMPLE_ENDPOINT_VID.equals(e.getVendorId()))
+ .findFirst()
+ .orElse(null);
}
- return endpoint;
+}
+return endpoint;
}
```
@@ -893,10 +1199,19 @@
// VendorId of the MCEndpoint on the MCCastingPlayer that the MCCastingApp desires to interact with after connection
let sampleEndpointVid: Int = 65521
...
-// select the MCEndpoint on the MCCastingPlayer to invoke the command on
-if let endpoint: MCEndpoint = castingPlayer.endpoints().filter({ $0.vendorId().intValue == sampleEndpointVid}).first
-{
-...
+
+// Select the MCEndpoint on the MCCastingPlayer to invoke the command on
+static func selectEndpoint(from castingPlayer: MCCastingPlayer, sampleEndpointVid: Int) -> MCEndpoint? {
+ Log.info("MCEndpointSelector.selectEndpoint()")
+
+ if let endpoint = castingPlayer.endpoints().filter({ $0.vendorId().intValue == sampleEndpointVid }).first {
+ Log.info("MCEndpointSelector.selectEndpoint() Found endpoint matching the sampleEndpointVid: \(sampleEndpointVid)")
+ return endpoint
+ }
+ ...
+
+ Log.error("No endpoint matching the example VID or identifier 1 found")
+ return nil
}
```
diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java
index 1bf95ef..b61b63f 100644
--- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java
+++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java
@@ -128,24 +128,26 @@
() -> {
Log.d(TAG, "onViewCreated() calling CastingPlayer.verifyOrEstablishConnection()");
- IdentificationDeclarationOptions idOptions = new IdentificationDeclarationOptions();
- TargetAppInfo targetAppInfo = new TargetAppInfo();
- targetAppInfo.vendorId = DESIRED_TARGET_APP_VENDOR_ID;
+ IdentificationDeclarationOptions idOptions;
+ TargetAppInfo targetAppInfo = new TargetAppInfo(DESIRED_TARGET_APP_VENDOR_ID);
if (useCommissionerGeneratedPasscode) {
- idOptions.commissionerPasscode = true;
- targetAppInfo.vendorId = DESIRED_TARGET_APP_VENDOR_ID_FOR_CGP_FLOW;
+ // Set commissionerPasscode to true for CastingPlayer/Commissioner-Generated
+ // passcode commissioning.
+ idOptions = new IdentificationDeclarationOptions(false, false, true, false, false);
+ targetAppInfo = new TargetAppInfo(DESIRED_TARGET_APP_VENDOR_ID_FOR_CGP_FLOW);
Log.d(
TAG,
"onViewCreated() calling CastingPlayer.verifyOrEstablishConnection() Target Content Application Vendor ID: "
- + targetAppInfo.vendorId
+ + targetAppInfo.getVendorId()
+ ", useCommissionerGeneratedPasscode: "
+ useCommissionerGeneratedPasscode);
} else {
+ idOptions = new IdentificationDeclarationOptions();
Log.d(
TAG,
"onViewCreated() calling CastingPlayer.verifyOrEstablishConnection() Target Content Application Vendor ID: "
- + targetAppInfo.vendorId);
+ + targetAppInfo.getVendorId());
}
idOptions.addTargetAppInfo(targetAppInfo);
@@ -242,21 +244,21 @@
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- String passcode = input.getText().toString();
+ String userEnteredPasscode = input.getText().toString();
Log.i(
TAG,
- "displayPasscodeInputDialog() User entered CastingPlayer/Commissioner-Generated passcode: "
- + passcode);
+ "displayPasscodeInputDialog() user-entered CastingPlayer/Commissioner-Generated passcode: "
+ + userEnteredPasscode);
// Display the user entered passcode on the screen
connectionFragmentStatusTextView.setText(
- "Continue Connecting with user entered CastingPlayer/Commissioner-Generated passcode: "
- + passcode
+ "Continue Connecting with user-entered CastingPlayer/Commissioner-Generated passcode: "
+ + userEnteredPasscode
+ "\n\n");
long passcodeLongValue = DEFAULT_COMMISSIONER_GENERATED_PASSCODE;
try {
- passcodeLongValue = Long.parseLong(passcode);
+ passcodeLongValue = Long.parseLong(userEnteredPasscode);
Log.i(
TAG,
"displayPasscodeInputDialog() User entered CastingPlayer/Commissioner-Generated passcode: "
@@ -268,12 +270,12 @@
+ nfe);
connectionFragmentStatusTextView.setText(
"User entered CastingPlayer/Commissioner-Generated passcode is not a valid integer: "
- + passcode
+ + userEnteredPasscode
+ "\n\n");
}
- // Update the CommissionableData DataProvider with the user entered
- // CastingPlayer/Commissioner-Generated setup passcode. This is mandatory for
+ // Update the CommissionableData DataProvider with the user-entered
+ // CastingPlayer / Commissioner-Generated setup passcode. This is mandatory for
// Commissioner-Generated passcode commissioning since the commissioning session's PAKE
// verifier needs to be updated with the entered passcode.
InitializationExample.commissionableDataProvider.updateCommissionableDataSetupPasscode(
diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/InitializationExample.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/InitializationExample.java
index 6cae9ab..6ccf2a3 100644
--- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/InitializationExample.java
+++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/InitializationExample.java
@@ -28,10 +28,6 @@
public class InitializationExample {
private static final String TAG = InitializationExample.class.getSimpleName();
- // Dummy values for commissioning demonstration only. These are hard coded in the example tv-app:
- // connectedhomeip/examples/tv-app/tv-common/src/AppTv.cpp
- private static final long DUMMY_SETUP_PASSCODE = 20202021;
- private static final int DUMMY_DISCRIMINATOR = 3874;
/**
* DataProvider implementation for the Unique ID that is used by the SDK to generate the Rotating
@@ -53,6 +49,12 @@
* through commissioning
*/
public static class CommissionableDataProvider implements DataProvider<CommissionableData> {
+ // Dummy values for commissioning demonstration only. These are hard coded in the example
+ // tv-app:
+ // connectedhomeip/examples/tv-app/tv-common/src/AppTv.cpp
+ private static final long DUMMY_SETUP_PASSCODE = 20202021;
+ private static final int DUMMY_DISCRIMINATOR = 3874;
+
CommissionableData commissionableData =
new CommissionableData(DUMMY_SETUP_PASSCODE, DUMMY_DISCRIMINATOR);
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/IdentificationDeclarationOptions.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/IdentificationDeclarationOptions.java
index 9b64b89..48c7ace 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/IdentificationDeclarationOptions.java
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/IdentificationDeclarationOptions.java
@@ -27,21 +27,29 @@
private final short CHIP_DEVICE_CONFIG_UDC_MAX_TARGET_APPS =
getChipDeviceConfigUdcMaxTargetApps();
+ /** Default constructor. */
public IdentificationDeclarationOptions() {}
+ /**
+ * Constructor to set all fields.
+ *
+ * @param noPasscode the no passcode flag.
+ * @param cdUponPasscodeDialog the cd upon passcode dialog flag.
+ * @param commissionerPasscode the commissioner passcode flag.
+ * @param commissionerPasscodeReady the commissioner passcode ready flag.
+ * @param cancelPasscode the cancel passcode flag.
+ */
public IdentificationDeclarationOptions(
boolean noPasscode,
boolean cdUponPasscodeDialog,
boolean commissionerPasscode,
boolean commissionerPasscodeReady,
- boolean cancelPasscode,
- List<TargetAppInfo> targetAppInfos) {
+ boolean cancelPasscode) {
this.noPasscode = noPasscode;
this.cdUponPasscodeDialog = cdUponPasscodeDialog;
this.commissionerPasscode = commissionerPasscode;
this.commissionerPasscodeReady = commissionerPasscodeReady;
this.cancelPasscode = cancelPasscode;
- this.targetAppInfos = targetAppInfos != null ? targetAppInfos : new ArrayList<>();
}
/**
@@ -57,28 +65,28 @@
* Passcode input dialog, and instead send a CommissionerDeclaration message if a commissioning
* Passcode is needed.
*/
- public boolean noPasscode = false;
+ private boolean noPasscode = false;
/**
* Feature: Coordinate Passcode Dialogs - Flag to instruct the Commissioner to send a
* CommissionerDeclaration message when the Passcode input dialog on the Commissioner has been
* shown to the user.
*/
- public boolean cdUponPasscodeDialog = false;
+ private boolean cdUponPasscodeDialog = false;
/**
* Feature: Commissioner-Generated Passcode - Flag to instruct the Commissioner to use the
* Commissioner-generated Passcode for commissioning.
*/
- public boolean commissionerPasscode = false;
+ private boolean commissionerPasscode = false;
/**
* Feature: Commissioner-Generated Passcode - Flag to indicate whether or not the Commissionee has
* obtained the Commissioner Passcode from the user and is therefore ready for commissioning.
*/
- public boolean commissionerPasscodeReady = false;
+ private boolean commissionerPasscodeReady = false;
/**
* Feature: Coordinate Passcode Dialogs Flag - to indicate when the Commissionee user has decided
* to exit the commissioning process.
*/
- public boolean cancelPasscode = false;
+ private boolean cancelPasscode = false;
/**
* Feature: Target Content Application - The set of content app Vendor IDs (and optionally,
* Product IDs) that can be used for authentication. Also, if TargetAppInfo is passed in,
@@ -104,6 +112,26 @@
return true;
}
+ public boolean isNoPasscode() {
+ return noPasscode;
+ }
+
+ public boolean isCdUponPasscodeDialog() {
+ return cdUponPasscodeDialog;
+ }
+
+ public boolean isCommissionerPasscode() {
+ return commissionerPasscode;
+ }
+
+ public boolean isCommissionerPasscodeReady() {
+ return commissionerPasscodeReady;
+ }
+
+ public boolean isCancelPasscode() {
+ return cancelPasscode;
+ }
+
public List<TargetAppInfo> getTargetAppInfoList() {
return targetAppInfos;
}
@@ -129,11 +157,7 @@
sb.append("IdentificationDeclarationOptions::targetAppInfos list: \n");
for (TargetAppInfo targetAppInfo : targetAppInfos) {
- sb.append("\t\tTargetAppInfo - Vendor ID: ")
- .append(targetAppInfo.vendorId)
- .append(", Product ID: ")
- .append(targetAppInfo.productId)
- .append("\n");
+ sb.append("\t\t").append(targetAppInfo).append("\n");
}
return sb.toString();
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/TargetAppInfo.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/TargetAppInfo.java
index e8b0553..ab3c70f 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/TargetAppInfo.java
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/TargetAppInfo.java
@@ -19,7 +19,55 @@
*/
public class TargetAppInfo {
/** Target Target Content Application Vendor ID, null means unspecified */
- public Integer vendorId;
+ private Integer vendorId;
/** Target Target Content Application Product ID, null means unspecified */
- public Integer productId;
+ private Integer productId;
+
+ /**
+ * Constructor to set both vendorId and productId.
+ *
+ * @param vendorId the vendor ID, null means unspecified.
+ * @param productId the product ID, null means unspecified.
+ */
+ public TargetAppInfo(Integer vendorId, Integer productId) {
+ this.vendorId = vendorId;
+ this.productId = productId;
+ }
+
+ /**
+ * Constructor to set only the vendorId.
+ *
+ * @param vendorId the vendor ID, null means unspecified.
+ */
+ public TargetAppInfo(Integer vendorId) {
+ this.vendorId = vendorId;
+ }
+
+ /**
+ * Getter for vendorId.
+ *
+ * @return the vendor ID, null means unspecified.
+ */
+ public Integer getVendorId() {
+ return vendorId;
+ }
+
+ /**
+ * Getter for productId.
+ *
+ * @return the product ID, null means unspecified.
+ */
+ public Integer getProductId() {
+ return productId;
+ }
+
+ /**
+ * Returns a string representation of the object.
+ *
+ * @return a string representation of the object.
+ */
+ @Override
+ public String toString() {
+ return "TargetAppInfo Vendor ID:" + vendorId + ", Product ID:" + productId;
+ }
}
diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift
index 13293d9..895b4a5 100644
--- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift
+++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift
@@ -67,8 +67,8 @@
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, calling getTopMostViewController()")
if let topViewController = self.getTopMostViewController() {
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, calling displayPasscodeInputDialog()")
- self.displayPasscodeInputDialog(on: topViewController, continueConnecting: { passcode in
- self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, Continuing to connect with user entered MCCastingPlayer/Commissioner-Generated passcode: \(passcode)")
+ self.displayPasscodeInputDialog(on: topViewController, continueConnecting: { userEnteredPasscode in
+ self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, Continuing to connect with user entered MCCastingPlayer/Commissioner-Generated passcode: \(userEnteredPasscode)")
// Update the CommissionableData in the client defined MCAppParametersDataSource with the user
// entered CastingPlayer/Commissioner-Generated setup passcode. This is mandatory for the
@@ -79,26 +79,44 @@
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback calling MCInitializationExample.getAppParametersDataSource()")
if let dataSource = initializationExample.getAppParametersDataSource() {
let newCommissionableData = MCCommissionableData(
- passcode: UInt32(passcode) ?? 0,
+ passcode: UInt32(userEnteredPasscode) ?? 0,
discriminator: 0,
spake2pIterationCount: 1000,
spake2pVerifier: nil,
spake2pSalt: nil
)
dataSource.update(newCommissionableData)
- self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, Updated MCAppParametersDataSource instance with new MCCommissionableData.")
+ self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, Updated MCAppParametersDataSource instance with new MCCommissionableData.")
} else {
- self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed")
+ self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed, calling stopConnecting()")
self.connectionStatus = "Failed to update the MCAppParametersDataSource with the user entered passcode: \n\nRoute back and try again."
+ self.connectionSuccess = false
+ // Since we failed to update the passcode, Attempt to cancel the connection attempt with
+ // the CastingPlayer/Commissioner.
+ let err = selectedCastingPlayer?.stopConnecting()
+ if err == nil {
+ self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed, then stopConnecting() succeeded")
+ } else {
+ self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed, then stopConnecting() failed due to: \(err)")
+ }
+ return
}
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, calling MCCastingPlayer.continueConnecting()")
let errContinue = selectedCastingPlayer?.continueConnecting()
if errContinue == nil {
- self.connectionStatus = "Continuing to connect with user entered passcode: \(passcode)"
+ self.connectionStatus = "Continuing to connect with user entered passcode: \(userEnteredPasscode)"
} else {
self.connectionStatus = "Continue Connecting to Casting Player failed with: \(String(describing: errContinue)) \n\nRoute back and try again."
self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, MCCastingPlayer.continueConnecting() failed due to: \(errContinue)")
+ // Since continueConnecting() failed, Attempt to cancel the connection attempt with
+ // the CastingPlayer/Commissioner.
+ let err = selectedCastingPlayer?.stopConnecting()
+ if err == nil {
+ self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, MCCastingPlayer.continueConnecting() failed, then stopConnecting() succeeded")
+ } else {
+ self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, MCCastingPlayer.continueConnecting() failed, then stopConnecting() failed due to: \(err)")
+ }
}
}, cancelConnecting: {
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, Connection attempt cancelled by the user, calling MCCastingPlayer.stopConnecting()")
diff --git a/examples/tv-casting-app/linux/simple-app-helper.cpp b/examples/tv-casting-app/linux/simple-app-helper.cpp
index 8fc0e7f..3cf13fa 100644
--- a/examples/tv-casting-app/linux/simple-app-helper.cpp
+++ b/examples/tv-casting-app/linux/simple-app-helper.cpp
@@ -394,6 +394,10 @@
targetCastingPlayer = castingPlayers.at(index);
gCommissionerGeneratedPasscodeFlowRunning = false;
+
+ // Specify the TargetApp that the client wants to interact with after commissioning. If this value is passed in,
+ // VerifyOrEstablishConnection() will force UDC, in case the desired TargetApp is not found in the on-device
+ // CastingStore
matter::casting::core::IdentificationDeclarationOptions idOptions;
chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo;
targetAppInfo.vendorId = kDesiredEndpointVendorId;
@@ -455,17 +459,17 @@
return PrintAllCommands();
}
char * eptr;
- uint32_t passcode = (uint32_t) strtol(argv[1], &eptr, 10);
+ uint32_t userEnteredPasscode = (uint32_t) strtol(argv[1], &eptr, 10);
if (gAwaitingCommissionerPasscodeInput)
{
- ChipLogProgress(AppServer, "CommandHandler() setcommissionerpasscode user entered passcode: %d", passcode);
+ ChipLogProgress(AppServer, "CommandHandler() setcommissionerpasscode user-entered passcode: %d", userEnteredPasscode);
gAwaitingCommissionerPasscodeInput = false;
// Per connectedhomeip/examples/platform/linux/LinuxCommissionableDataProvider.h: We don't support overriding the
- // passcode post-init (it is deprecated!). Therefore we need to initiate a new provider with the user entered
+ // passcode post-init (it is deprecated!). Therefore we need to initiate a new provider with the user-entered
// Commissioner-generated passcode, and then update the CastigApp's AppParameters to update the commissioning session's
// passcode.
- LinuxDeviceOptions::GetInstance().payload.setUpPINCode = passcode;
+ LinuxDeviceOptions::GetInstance().payload.setUpPINCode = userEnteredPasscode;
LinuxCommissionableDataProvider gCommissionableDataProvider;
CHIP_ERROR err = CHIP_NO_ERROR;
err = InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance());
@@ -474,6 +478,7 @@
ChipLogError(AppServer,
"CommandHandler() setcommissionerpasscode InitCommissionableDataProvider() err %" CHIP_ERROR_FORMAT,
err.Format());
+ return err;
}
// Update the CommissionableDataProvider stored in this CastingApp's AppParameters and the CommissionableDataProvider to
// be used for the commissioning session.
@@ -483,14 +488,27 @@
ChipLogError(AppServer,
"CommandHandler() setcommissionerpasscode InitCommissionableDataProvider() err %" CHIP_ERROR_FORMAT,
err.Format());
+ return err;
}
// Continue Connecting to the target CastingPlayer with the user entered Commissioner-generated Passcode.
err = targetCastingPlayer->ContinueConnecting();
if (err != CHIP_NO_ERROR)
{
- ChipLogError(AppServer, "CommandHandler() setcommissionerpasscode ContinueConnecting() err %" CHIP_ERROR_FORMAT,
+ ChipLogError(AppServer,
+ "CommandHandler() setcommissionerpasscode ContinueConnecting() failed due to err %" CHIP_ERROR_FORMAT,
err.Format());
+ // Since continueConnecting() failed, Attempt to cancel the connection attempt with
+ // the CastingPlayer/Commissioner by calling StopConnecting().
+ err = targetCastingPlayer->StopConnecting();
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer,
+ "CommandHandler() setcommissionerpasscode, ContinueConnecting() failed and then StopConnecting "
+ "failed due to err %" CHIP_ERROR_FORMAT,
+ err.Format());
+ }
+ return err;
}
}
else
@@ -498,6 +516,7 @@
ChipLogError(
AppServer,
"CommandHandler() setcommissionerpasscode, no Commissioner-Generated passcode input expected at this time.");
+ return CHIP_ERROR_INVALID_ARGUMENT;
}
}
if (strcmp(argv[0], "stop-connecting") == 0)
@@ -507,6 +526,7 @@
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "CommandHandler() stop-connecting, err %" CHIP_ERROR_FORMAT, err.Format());
+ return err;
}
}
if (strcmp(argv[0], "print-bindings") == 0)