Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Use GetDeviceBeingCommissioned for network commissioning #11658

Merged
merged 2 commits into from
Nov 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import chip.devicecontroller.ChipClusters.NetworkCommissioningCluster
import com.google.chip.chiptool.ChipClient
import com.google.chip.chiptool.R
Expand All @@ -37,16 +36,11 @@ import kotlinx.android.synthetic.main.enter_thread_network_fragment.xpanIdEd
import kotlinx.android.synthetic.main.enter_wifi_network_fragment.pwdEd
import kotlinx.android.synthetic.main.enter_wifi_network_fragment.ssidEd
import kotlinx.android.synthetic.main.enter_wifi_network_fragment.view.saveNetworkBtn
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

/**
* Fragment to collect Wi-Fi network information from user and send it to device being provisioned.
*/
class EnterNetworkFragment : Fragment() {

private lateinit var scope: CoroutineScope

private val networkType: ProvisionNetworkType
get() = requireNotNull(
ProvisionNetworkType.fromName(arguments?.getString(ARG_PROVISION_NETWORK_TYPE))
Expand All @@ -57,15 +51,13 @@ class EnterNetworkFragment : Fragment() {
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
scope = viewLifecycleOwner.lifecycleScope

val layoutRes = when (networkType) {
ProvisionNetworkType.WIFI -> R.layout.enter_wifi_network_fragment
ProvisionNetworkType.THREAD -> R.layout.enter_thread_network_fragment
}

if (USE_HARDCODED_WIFI) {
scope.launch { saveHardcodedWifiNetwork() }
saveHardcodedWifiNetwork()
}

return inflater.inflate(layoutRes, container, false).apply {
Expand All @@ -75,17 +67,17 @@ class EnterNetworkFragment : Fragment() {

private fun onSaveNetworkClicked() {
if (networkType == ProvisionNetworkType.WIFI) {
scope.launch { saveWifiNetwork() }
saveWifiNetwork()
} else {
scope.launch { saveThreadNetwork() }
saveThreadNetwork()
}
}

private suspend fun saveHardcodedWifiNetwork() {
private fun saveHardcodedWifiNetwork() {
addAndEnableWifiNetwork(HARDCODED_WIFI_SSID, HARDCODED_WIFI_PASSWORD)
}

private suspend fun saveWifiNetwork() {
private fun saveWifiNetwork() {
val ssid = ssidEd?.text
val pwd = pwdEd?.text

Expand All @@ -97,15 +89,12 @@ class EnterNetworkFragment : Fragment() {
addAndEnableWifiNetwork(ssid.toString(), pwd.toString())
}

private suspend fun addAndEnableWifiNetwork(ssid: String, password: String) {
private fun addAndEnableWifiNetwork(ssid: String, password: String) {
// Uses UTF-8 as default
val ssidBytes = ssid.toByteArray()
val pwdBytes = password.toByteArray()

val devicePtr =
ChipClient.getConnectedDevicePointer(requireContext(), DeviceIdUtil.getLastDeviceId(requireContext()))
val cluster = NetworkCommissioningCluster(devicePtr, /* endpointId = */ 0)

val cluster = createNetworkCommissioningCluster()
val enableNetworkCallback = object :
NetworkCommissioningCluster.EnableNetworkResponseCallback {
override fun onSuccess(errorCode: Int, debugText: String) {
Expand Down Expand Up @@ -157,7 +146,7 @@ class EnterNetworkFragment : Fragment() {
}, ssidBytes, pwdBytes, /* breadcrumb = */ 0L, ADD_NETWORK_TIMEOUT)
}

private suspend fun saveThreadNetwork() {
private fun saveThreadNetwork() {
val channelStr = channelEd.text
val panIdStr = panIdEd.text

Expand Down Expand Up @@ -193,9 +182,7 @@ class EnterNetworkFragment : Fragment() {
return
}

val devicePtr =
ChipClient.getConnectedDevicePointer(requireContext(), DeviceIdUtil.getLastDeviceId(requireContext()))
val cluster = NetworkCommissioningCluster(devicePtr, /* endpointId = */ 0)
val cluster = createNetworkCommissioningCluster()

val operationalDataset = makeThreadOperationalDataset(
channelStr.toString().toInt(),
Expand Down Expand Up @@ -290,13 +277,20 @@ class EnterNetworkFragment : Fragment() {
return dataset
}

private fun createNetworkCommissioningCluster(): NetworkCommissioningCluster {
val devicePtr = ChipClient.getDeviceController(requireContext())
.getDeviceBeingCommissionedPointer(DeviceIdUtil.getLastDeviceId(requireContext()))
return NetworkCommissioningCluster(devicePtr, NETWORK_COMMISSIONING_CLUSTER_ENDPOINT)
}

private fun String.hexToByteArray(): ByteArray {
return chunked(2).map { byteStr -> byteStr.toUByte(16).toByte() }.toByteArray()
}

companion object {
private const val TAG = "EnterNetworkFragment"
private const val ARG_PROVISION_NETWORK_TYPE = "provision_network_type"
private const val NETWORK_COMMISSIONING_CLUSTER_ENDPOINT = 0

// TODO(#5035): remove hardcoded option when delayed commands work.
private const val USE_HARDCODED_WIFI = false
Expand Down
26 changes: 26 additions & 0 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,39 @@ JNI_METHOD(void, stopDevicePairing)(JNIEnv * env, jobject self, jlong handle, jl
}
}

JNI_METHOD(jlong, getDeviceBeingCommissionedPointer)(JNIEnv * env, jobject self, jlong handle, jlong nodeId)
{
chip::DeviceLayer::StackLock lock;
CHIP_ERROR err = CHIP_NO_ERROR;
AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);

CommissioneeDeviceProxy * commissioneeDevice = nullptr;
err = wrapper->Controller()->GetDeviceBeingCommissioned(static_cast<NodeId>(nodeId), &commissioneeDevice);

if (commissioneeDevice == nullptr)
{
ChipLogError(Controller, "Commissionee device was nullptr");
err = CHIP_ERROR_INCORRECT_STATE;
}

if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to get commissionee device: %s", ErrorStr(err));
JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err);
return 0;
}

return reinterpret_cast<jlong>(commissioneeDevice);
}

JNI_METHOD(void, getConnectedDevicePointer)(JNIEnv * env, jobject self, jlong handle, jlong nodeId, jlong callbackHandle)
{
chip::DeviceLayer::StackLock lock;
AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);

GetConnectedDeviceCallback * connectedDeviceCallback = reinterpret_cast<GetConnectedDeviceCallback *>(callbackHandle);
VerifyOrReturn(connectedDeviceCallback != nullptr, ChipLogError(Controller, "GetConnectedDeviceCallback handle is nullptr"));
wrapper->Controller()->GetCompressedFabricId();
wrapper->Controller()->GetConnectedDevice(nodeId, &connectedDeviceCallback->mOnSuccess, &connectedDeviceCallback->mOnFailure);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ public void pairDevice(BluetoothGatt bleServer, int connId, long deviceId, long
/**
* Pair a device connected through BLE.
*
* <p>TODO(#7985): Annotate csrNonce as Nullable.
*
* @param bleServer the BluetoothGatt representing the BLE connection to the device
* @param connId the BluetoothGatt Id representing the BLE connection to the device
* @param deviceId the node ID to assign to the device
Expand Down Expand Up @@ -100,6 +98,14 @@ public void unpairDevice(long deviceId) {
unpairDevice(deviceControllerPtr, deviceId);
}

/**
* Returns a pointer to a device currently being commissioned. This should be used before the
* device is operationally available.
*/
public long getDeviceBeingCommissionedPointer(long nodeId) {
return getDeviceBeingCommissionedPointer(deviceControllerPtr, nodeId);
}

/**
* Through GetConnectedDeviceCallback, returns a pointer to a connected device or an error.
*
Expand Down Expand Up @@ -251,6 +257,8 @@ private native void pairDeviceWithAddress(

private native void unpairDevice(long deviceControllerPtr, long deviceId);

private native long getDeviceBeingCommissionedPointer(long deviceControllerPtr, long nodeId);

private native void getConnectedDevicePointer(
long deviceControllerPtr, long deviceId, long callbackHandle);

Expand Down