Skip to content

Commit

Permalink
Merge branch 'master' into feature/app-install-flow-public
Browse files Browse the repository at this point in the history
  • Loading branch information
lazarkov authored Jul 1, 2024
2 parents 1d3a69f + e7a153f commit 5c4c4df
Show file tree
Hide file tree
Showing 26 changed files with 655 additions and 181 deletions.
509 changes: 412 additions & 97 deletions examples/tv-casting-app/APIs.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -128,24 +128,26 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
() -> {
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);
Expand Down Expand Up @@ -242,21 +244,21 @@ private void displayPasscodeInputDialog(Context context) {
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: "
Expand All @@ -268,12 +270,12 @@ public void onClick(DialogInterface dialog, int which) {
+ 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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -53,6 +49,12 @@ public byte[] get() {
* 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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,29 @@ public class IdentificationDeclarationOptions {
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<>();
}

/**
Expand All @@ -57,28 +65,28 @@ public IdentificationDeclarationOptions(
* 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,
Expand All @@ -104,6 +112,26 @@ public boolean addTargetAppInfo(TargetAppInfo targetAppInfo) {
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;
}
Expand All @@ -129,11 +157,7 @@ public String toString() {
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ class MCConnectionExampleViewModel: ObservableObject {
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
Expand All @@ -79,26 +79,44 @@ class MCConnectionExampleViewModel: ObservableObject {
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()")
Expand Down
Loading

0 comments on commit 5c4c4df

Please sign in to comment.