diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt
index 2b2078dde5e688..75353ffa5ea355 100644
--- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt
+++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt
@@ -122,6 +122,11 @@ class CHIPToolActivity :
startActivity(redirectIntent)
}
+ override fun handleEnhancedSetupFlowClicked() {
+ Toast.makeText(this, "Enhanced Setup Flow", Toast.LENGTH_SHORT).show()
+ showFragment(DeviceProvisioningFragment.newInstance(deviceInfo!!, null))
+ }
+
override fun setNetworkType(type: ProvisionNetworkType?) {
networkType = type
}
diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/GenericChipDeviceListener.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/GenericChipDeviceListener.kt
index 2eb2a1c77fa042..bc333f3153ee0b 100644
--- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/GenericChipDeviceListener.kt
+++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/GenericChipDeviceListener.kt
@@ -60,4 +60,12 @@ open class GenericChipDeviceListener : ChipDeviceController.CompletionListener {
override fun onICDRegistrationComplete(errorCode: Long, icdDeviceInfo: ICDDeviceInfo) {
// No op
}
+
+ override fun onTermsAndConditionsRequired() {
+ // No op
+ }
+
+ override fun onTermsAndConditionsRequiredComplete(termsAndConditionsAcknowledgements: Int, termsAndConditionsVersion: Int) {
+ // No op
+ }
}
diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt
index 69bfdc109912c9..9f23e67db4f559 100644
--- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt
+++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt
@@ -69,7 +69,7 @@ class SelectActionFragment : Fragment() {
binding.basicClusterBtn.setOnClickListener { handleBasicClicked() }
binding.attestationTestBtn.setOnClickListener { handleAttestationTestClicked() }
binding.clusterInteractionBtn.setOnClickListener { handleClusterInteractionClicked() }
- binding.provisionCustomFlowBtn.setOnClickListener { handleProvisionCustomFlowClicked() }
+ binding.provisionCustomFlowReadFromLedgerBtn.setOnClickListener { handleProvisionCustomFlowClicked() }
binding.wildcardBtn.setOnClickListener { handleWildcardClicked() }
binding.unpairDeviceBtn.setOnClickListener { handleUnpairDeviceClicked() }
binding.groupSettingBtn.setOnClickListener { handleGroupSettingClicked() }
diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/DeviceProvisioningFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/DeviceProvisioningFragment.kt
index 97b2576827079a..3466fe4e746c13 100644
--- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/DeviceProvisioningFragment.kt
+++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/DeviceProvisioningFragment.kt
@@ -314,6 +314,14 @@ class DeviceProvisioningFragment : Fragment() {
.show()
}
}
+
+ override fun onTermsAndConditionsRequired() {
+ }
+
+ override fun onTermsAndConditionsRequiredComplete(termsAndConditionsAcknowledgements: Int, termsAndConditionsVersion: Int) {
+ Log.d(TAG, "onTermsAndConditionsRequiredComplete: $termsAndConditionsAcknowledgements, $termsAndConditionsVersion")
+ deviceController.updateTermsAndConditionsAcknowledgements(termsAndConditionsAcknowledgements, termsAndConditionsVersion)
+ }
}
private fun ByteArray.toHex(): String =
diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt
index 411f51eae3de73..d8200b22c7ef2a 100644
--- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt
+++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt
@@ -80,8 +80,8 @@ class CHIPDeviceDetailsFragment : Fragment() {
// commissioningFlow = 2 (Custom), read device info from Ledger
if (deviceInfo.commissioningFlow == 2) {
- binding.customFlowBtn.visibility = View.VISIBLE
- binding.customFlowBtn.setOnClickListener {
+ binding.customFlowReadFromLedgerBtn.visibility = View.VISIBLE
+ binding.customFlowReadFromLedgerBtn.setOnClickListener {
FragmentUtil.getHost(this@CHIPDeviceDetailsFragment, Callback::class.java)
?.handleReadFromLedgerClicked(deviceInfo)
}
diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt
index 92edce9da1331b..0f6fce6e95d85f 100644
--- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt
+++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt
@@ -25,14 +25,19 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.Toast
import androidx.fragment.app.Fragment
import com.android.volley.Request
+import com.android.volley.Response.Listener
import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.Volley
import com.google.chip.chiptool.R
import com.google.chip.chiptool.databinding.ChipLedgerInfoFragmentBinding
import com.google.chip.chiptool.util.FragmentUtil
import com.google.gson.Gson
+import java.io.BufferedReader
+import java.io.InputStreamReader
+import org.json.JSONObject
/** Show the [CHIPDeviceInfo] from Ledger */
class CHIPLedgerDetailsFragment : Fragment() {
@@ -55,7 +60,7 @@ class CHIPLedgerDetailsFragment : Fragment() {
// Ledger api url
val url =
- Uri.parse(context!!.getString(R.string.dcl_api_root_url))
+ Uri.parse(DCL_API_ROOT_URL)
.buildUpon()
.appendPath("${deviceInfo.vendorId}")
.appendPath("${deviceInfo.productId}")
@@ -63,53 +68,42 @@ class CHIPLedgerDetailsFragment : Fragment() {
.toString()
Log.d(TAG, "Dcl request Url: $url")
- // Ledger API call
- val jsonObjectRequest =
- JsonObjectRequest(
- Request.Method.GET,
- url,
- null,
- { response ->
- Log.d(TAG, "Response from dcl $response")
-
- // parse redirect Url
- val responseJson = response.getJSONObject(context!!.getString(R.string.dcl_response_key))
- val redirectUrl =
- responseJson.getString(context!!.getString(R.string.dcl_custom_flow_url_key))
- Log.d(TAG, "Redirect Url from Ledger: $redirectUrl")
- binding.commissioningFlowUrlTv.text = redirectUrl
-
- // generate redirect payload
- val gson = Gson()
- val payloadJson = gson.toJson(deviceInfo)
- val payloadBase64 = Base64.encodeToString(payloadJson.toByteArray(), Base64.DEFAULT)
- val redirectUrlWithPayload =
- Uri.parse(redirectUrl)
- .buildUpon()
- .appendQueryParameter("payload", payloadBase64)
- .appendQueryParameter(
- "returnUrl",
- context!!.getString(R.string.custom_flow_return_url)
- )
- .build()
- .toString()
-
- Log.d(TAG, "Redirect Url with Payload: $redirectUrlWithPayload")
- binding.redirectBtn.setOnClickListener {
- FragmentUtil.getHost(this@CHIPLedgerDetailsFragment, Callback::class.java)
- ?.handleCustomFlowRedirectClicked(redirectUrlWithPayload)
- }
+ val context = getContext()!!
+ val mockDclRequestsResponsesRaw = readRawResourceFile(R.raw.mock_dcl_responses_json)
+ val mockDclRequestsResponses: org.json.JSONArray = org.json.JSONArray(mockDclRequestsResponsesRaw)
+
+ val mockDclRequestsResponseMap = HashMap()
+ for (i in 0 until mockDclRequestsResponses.length()) {
+ val mockDclRequestsResponse = mockDclRequestsResponses.getJSONObject(i)
+
+ val mockDclRequest: org.json.JSONObject = mockDclRequestsResponse.getJSONObject("request")
+ val mockDclResponse: org.json.JSONObject = mockDclRequestsResponse.getJSONObject("response")
- // enable redirect button
- binding.redirectBtn.visibility = View.VISIBLE
- },
- { error ->
- Log.e(TAG, "Dcl request failed: $error")
- binding.commissioningFlowUrlTv.text =
- context!!.getString(R.string.chip_ledger_info_commissioning_flow_url_not_available)
- }
- )
- queue.add(jsonObjectRequest)
+ val mockDclRequestURL = mockDclRequest.getString("url")
+ val mockDclResponseBody = mockDclResponse.getJSONObject("body")
+
+ mockDclRequestsResponseMap.put(mockDclRequestURL, mockDclResponseBody)
+ Log.d(TAG, "mockDclRequestURL= $mockDclRequestURL")
+ Log.d(TAG, "mockDclResponseBody= $mockDclResponseBody")
+ }
+
+ Log.d(TAG, "Request url= $url")
+ val response: org.json.JSONObject = mockDclRequestsResponseMap.get(url.toString())!!
+ Log.d(TAG, "Response from dcl $response")
+ Toast.makeText(context, "Enhanced Setup Flow: $response", Toast.LENGTH_LONG).show()
+
+ val enhancedSetupFlowOptions = response.optInt("enhancedSetupFlowOptions", 0)
+
+ if (0 != (enhancedSetupFlowOptions and 0b00000001)) {
+ Toast.makeText(context, "Enhanced Setup Flow supported!", Toast.LENGTH_SHORT).show()
+
+ binding.commissionBtn.setOnClickListener {
+ FragmentUtil.getHost(this@CHIPLedgerDetailsFragment, Callback::class.java)
+ ?.handleEnhancedSetupFlowClicked()
+ }
+
+ binding.commissionBtn.visibility = View.VISIBLE
+ }
return binding.root
}
@@ -119,15 +113,40 @@ class CHIPLedgerDetailsFragment : Fragment() {
_binding = null
}
+ private fun readRawResourceFile(resourceId: Int): String? {
+ return try {
+ val inputStream = resources.openRawResource(resourceId)
+ val bufferedReader = BufferedReader(InputStreamReader(inputStream))
+ val stringBuilder = StringBuilder()
+ var line: String? = bufferedReader.readLine()
+ while (line != null) {
+ stringBuilder.append(line)
+ line = bufferedReader.readLine()
+ }
+ bufferedReader.close()
+ inputStream.close()
+ stringBuilder.toString()
+ } catch (e: Exception) {
+ Log.e("MainActivity", "Error reading raw resource file", e)
+ null
+ }
+ }
+
/** Interface for notifying the host. */
interface Callback {
/** Notifies listener of Custom flow redirect button click. */
fun handleCustomFlowRedirectClicked(redirectUrl: String)
+
+ /** Notifies listener of Enhanced Setup flow button click. */
+ fun handleEnhancedSetupFlowClicked()
}
companion object {
private const val TAG = "CUSTOM_FLOW"
private const val ARG_DEVICE_INFO = "device_info"
+ private const val DCL_CUSTOM_FLOW_URL_KEY = "commissioningCustomFlowUrl";
+ private const val DCL_API_ROOT_URL = "https://on.dcl.csa-iot.org/dcl/model/models";
+ private const val CUSTOM_FLOW_RETURN_URL = "mt://modelinfo";
@JvmStatic
fun newInstance(deviceInfo: CHIPDeviceInfo): CHIPLedgerDetailsFragment {
diff --git a/examples/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml
index a1deab648adc9f..04df24030f35cd 100644
--- a/examples/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml
+++ b/examples/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml
@@ -220,7 +220,7 @@
tools:ignore="LabelFor" />
+
diff --git a/examples/android/CHIPTool/app/src/main/res/layout/select_action_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/select_action_fragment.xml
index 5824e8061a4e03..45af60768eb0d0 100644
--- a/examples/android/CHIPTool/app/src/main/res/layout/select_action_fragment.xml
+++ b/examples/android/CHIPTool/app/src/main/res/layout/select_action_fragment.xml
@@ -32,7 +32,7 @@
android:text="@string/provision_thread_credentials_btn_text" />
Loading...
Redirect
+ Commission
Not available
Commissioning flow Completed.
- https://dcl.dev.dsr-corporation.com/api/modelinfo/models
- result
- custom
- mt://modelinfo
Retrieve Endpoint List
Invoke
Select a command
diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp
index 93ab5ccd0a1012..bd0a44a2463f09 100644
--- a/src/controller/java/CHIPDeviceController-JNI.cpp
+++ b/src/controller/java/CHIPDeviceController-JNI.cpp
@@ -733,6 +733,9 @@ JNI_METHOD(void, pairDeviceWithAddress)
{
commissioningParams.SetDeviceAttestationDelegate(wrapper->GetDeviceAttestationDelegateBridge());
}
+
+ commissioningParams.SetTermsAndConditionsAcknowledgement((const TermsAndConditionsAcknowledgement){ 1, 1 });
+
err = wrapper->Controller()->PairDevice(static_cast(deviceId), rendezvousParams, commissioningParams);
if (err != CHIP_NO_ERROR)
@@ -933,6 +936,39 @@ JNI_METHOD(void, updateCommissioningNetworkCredentials)
}
}
+JNI_METHOD(void, updateTermsAndConditionsAcknowledgements)
+(JNIEnv * env, jobject self, jlong handle, jint acceptedTermsAndConditions, jint acceptedTermsAndConditionsVersion)
+{
+ ChipLogProgress(Controller, "updateTermsAndConditionsAcknowledgements() called");
+
+ // Check if the input values are within the range of uint16_t
+ if (acceptedTermsAndConditions < 0 || acceptedTermsAndConditions > 65535 || acceptedTermsAndConditionsVersion < 0 ||
+ acceptedTermsAndConditionsVersion > 65535)
+ {
+ jclass illegalArgumentExceptionClass = env->FindClass("java/lang/IllegalArgumentException");
+ if (illegalArgumentExceptionClass != nullptr)
+ {
+ env->ThrowNew(illegalArgumentExceptionClass, "Input values must be in the range 0 to 65535.");
+ }
+ return;
+ }
+
+ AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);
+
+ // Retrieve the commissioning parameters
+ CommissioningParameters commissioningParams = wrapper->GetAutoCommissioner()->GetCommissioningParameters();
+
+ TermsAndConditionsAcknowledgement termsAndConditionsAcknowledgement;
+ termsAndConditionsAcknowledgement.acceptedTermsAndConditions = static_cast(acceptedTermsAndConditions);
+ termsAndConditionsAcknowledgement.acceptedTermsAndConditionsVersion = static_cast(acceptedTermsAndConditionsVersion);
+
+ // Update the commissioning parameters with the new terms and conditions
+ commissioningParams.SetTermsAndConditionsAcknowledgement(termsAndConditionsAcknowledgement);
+
+ // Set the updated commissioning parameters back to the wrapper
+ wrapper->GetAutoCommissioner()->SetCommissioningParameters(commissioningParams);
+}
+
JNI_METHOD(void, updateCommissioningICDRegistrationInfo)
(JNIEnv * env, jobject self, jlong handle, jobject icdRegistrationInfo)
{
diff --git a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java
index 37e9e7093a1afc..034679eabe2032 100644
--- a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java
+++ b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java
@@ -580,6 +580,10 @@ public void updateCommissioningICDRegistrationInfo(ICDRegistrationInfo icdRegist
updateCommissioningICDRegistrationInfo(deviceControllerPtr, icdRegistrationInfo);
}
+ public void updateTermsAndConditionsAcknowledgements(int acceptedTermsAndConditions, int acceptedTermsAndConditionsVersion) throws java.lang.IllegalArgumentException {
+ updateTermsAndConditionsAcknowledgements(deviceControllerPtr, acceptedTermsAndConditions, acceptedTermsAndConditionsVersion);
+ }
+
public void unpairDevice(long deviceId) {
unpairDevice(deviceControllerPtr, deviceId);
}
@@ -1717,6 +1721,8 @@ private native void setUseJavaCallbackForNOCRequest(
private native void updateCommissioningNetworkCredentials(
long deviceControllerPtr, NetworkCredentials networkCredentials);
+ private native void updateTermsAndConditionsAcknowledgements(long deviceControllerPtr, int acceptedTermsAndConditions, int acceptedTermsAndConditionsVersion) throws java.lang.IllegalArgumentException;
+
private native void updateCommissioningICDRegistrationInfo(
long deviceControllerPtr, ICDRegistrationInfo icdRegistrationInfo);
@@ -1793,6 +1799,10 @@ void onScanNetworksSuccess(
Optional> threadScanResults);
}
+ public interface TermsAndConditionsListener {
+ void onTermsAndConditionsAcknowlegementRequired();
+ }
+
/** Interface to listen for callbacks from CHIPDeviceController. */
public interface CompletionListener {
@@ -1838,5 +1848,8 @@ void onReadCommissioningInfo(
/** Notifies when the registration flow for the ICD completes. */
void onICDRegistrationComplete(long errorCode, ICDDeviceInfo icdDeviceInfo);
+
+ void onTermsAndConditionsRequired();
+ void onTermsAndConditionsRequiredComplete(int termsAndConditionsAcknowledgements, int termsAndConditionsVersion);
}
}
diff --git a/src/controller/java/src/matter/controller/MatterController.kt b/src/controller/java/src/matter/controller/MatterController.kt
index 2e4ecb54da1fb9..d474b52fbdd494 100644
--- a/src/controller/java/src/matter/controller/MatterController.kt
+++ b/src/controller/java/src/matter/controller/MatterController.kt
@@ -59,6 +59,10 @@ interface MatterController : Closeable, InteractionClient {
/** Notifies the Commissioner when the OpCSR for the Comissionee is generated. */
fun onOpCSRGenerationComplete(csr: ByteArray)
+ fun onTermsAndConditionsRequired()
+
+ fun onTermsAndConditionsComplete()
+
/**
* Notifies when the ICD registration information (ICD symmetric key, check-in node ID and
* monitored subject) is required.