Skip to content

Commit

Permalink
[Android] Implement qr code generator (#33381)
Browse files Browse the repository at this point in the history
* Implement QR Code Parser

* Fix QR Code scan, static code

* Kotlin codestyle

* restore soft_ap feature
  • Loading branch information
joonhaengHeo authored May 10, 2024
1 parent 8122739 commit 93aa97d
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class CHIPToolActivity :
startActivity(redirectIntent)
}

override fun SetNetworkType(type: ProvisionNetworkType) {
override fun setNetworkType(type: ProvisionNetworkType?) {
networkType = type
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class SelectActionFragment : Fragment() {
/** Notifies listener of a click to manually input the CHIP device address. */
fun onShowDeviceAddressInput()

fun SetNetworkType(type: ProvisionNetworkType)
fun setNetworkType(type: ProvisionNetworkType?)
}

private fun showFragment(fragment: Fragment, showOnBack: Boolean = true) {
Expand All @@ -172,6 +172,7 @@ class SelectActionFragment : Fragment() {

/** Notifies listener of Scan QR code button click. */
private fun handleScanQrCodeClicked() {
getCallback()?.setNetworkType(null)
showFragment(BarcodeFragment.newInstance())
}

Expand Down Expand Up @@ -226,13 +227,13 @@ class SelectActionFragment : Fragment() {

/** Notifies listener of provision-WiFi-credentials button click. */
private fun handleProvisionWiFiCredentialsClicked() {
getCallback()?.SetNetworkType(ProvisionNetworkType.WIFI)
getCallback()?.setNetworkType(ProvisionNetworkType.WIFI)
showFragment(BarcodeFragment.newInstance())
}

/** Notifies listener of provision-Thread-credentials button click. */
private fun handleProvisionThreadCredentialsClicked() {
getCallback()?.SetNetworkType(ProvisionNetworkType.THREAD)
getCallback()?.setNetworkType(ProvisionNetworkType.THREAD)
showFragment(BarcodeFragment.newInstance())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@

package com.google.chip.chiptool.setuppayloadscanner

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
Expand All @@ -27,6 +32,10 @@ import androidx.fragment.app.Fragment
import com.google.chip.chiptool.R
import com.google.chip.chiptool.databinding.ChipDeviceInfoFragmentBinding
import com.google.chip.chiptool.util.FragmentUtil
import java.net.URLEncoder
import matter.onboardingpayload.OnboardingPayload
import matter.onboardingpayload.OnboardingPayloadException
import matter.onboardingpayload.QRCodeOnboardingPayloadGenerator

/** Show the [CHIPDeviceInfo]. */
class CHIPDeviceDetailsFragment : Fragment() {
Expand All @@ -35,6 +44,8 @@ class CHIPDeviceDetailsFragment : Fragment() {
private val binding
get() = _binding!!

private lateinit var onBoardingPayload: OnboardingPayload

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand All @@ -43,17 +54,13 @@ class CHIPDeviceDetailsFragment : Fragment() {
_binding = ChipDeviceInfoFragmentBinding.inflate(inflater, container, false)
deviceInfo = checkNotNull(requireArguments().getParcelable(ARG_DEVICE_INFO))

binding.versionTv.text = "${deviceInfo.version}"
binding.vendorIdTv.text = "${deviceInfo.vendorId}"
binding.productIdTv.text = "${deviceInfo.productId}"
binding.setupCodeTv.text = "${deviceInfo.setupPinCode}"
binding.discriminatorTv.text = "${deviceInfo.discriminator}"
binding.discoveryCapabilitiesTv.text =
requireContext()
.getString(
R.string.chip_device_info_discovery_capabilities_text,
deviceInfo.discoveryCapabilities
)
binding.versionEd.setText(deviceInfo.version.toString())
binding.vendorIdEd.setText(deviceInfo.vendorId.toString())
binding.productIdEd.setText(deviceInfo.productId.toString())
binding.setupCodeEd.setText(deviceInfo.setupPinCode.toString())
binding.discriminatorEd.setText(deviceInfo.discriminator.toString())
binding.serialNumberEd.setText(deviceInfo.serialNumber)
binding.discoveryCapabilitiesTv.text = "${deviceInfo.discoveryCapabilities}"

if (deviceInfo.optionalQrCodeInfoMap.isEmpty()) {
binding.vendorTagsLabelTv.visibility = View.GONE
Expand All @@ -70,7 +77,7 @@ class CHIPDeviceDetailsFragment : Fragment() {
}
}

binding.commissioningFlowTv.text = "${deviceInfo.commissioningFlow}"
binding.commissioningFlowEd.setText(deviceInfo.commissioningFlow.toString())

// commissioningFlow = 2 (Custom), read device info from Ledger
if (deviceInfo.commissioningFlow == 2) {
Expand All @@ -81,9 +88,74 @@ class CHIPDeviceDetailsFragment : Fragment() {
}
}

onBoardingPayload = deviceInfo.toSetupPayload()
binding.qrCodeTv.text =
QRCodeOnboardingPayloadGenerator(onBoardingPayload)
.payloadBase38RepresentationWithAutoTLVBuffer()

setDiscoveryCapabilitiesEditTextListener()
setQRCodeButtonListener()

return binding.root
}

private fun setDiscoveryCapabilitiesEditTextListener() {
binding.discoveryCapabilitiesEd.setText(onBoardingPayload.getRendezvousInformation().toString())
binding.discoveryCapabilitiesEd.addTextChangedListener(
object : TextWatcher {
override fun onTextChanged(value: CharSequence?, p1: Int, p2: Int, p3: Int) {
if (value.isNullOrEmpty()) {
return
}
onBoardingPayload.setRendezvousInformation(value.toString().toLong())
binding.discoveryCapabilitiesTv.text = "${onBoardingPayload.discoveryCapabilities}"
}

override fun afterTextChanged(p0: Editable?) {
// no_op
}

override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
// no_op
}
}
)
}

private fun setQRCodeButtonListener() {
binding.showQRCodeBtn.setOnClickListener {
onBoardingPayload.apply {
version = binding.versionEd.text.toString().toInt()
vendorId = binding.vendorIdEd.text.toString().toInt()
productId = binding.productIdEd.text.toString().toInt()
commissioningFlow = binding.commissioningFlowEd.text.toString().toInt()
setupPinCode = binding.setupCodeEd.text.toString().toLong()
discriminator = binding.discriminatorEd.text.toString().toInt()
val serialNumber = binding.serialNumberEd.text.toString()
try {
removeSerialNumber()
} catch (e: OnboardingPayloadException) {
Log.d(TAG, "Serial Number not set!", e)
}
if (serialNumber.isNotEmpty()) {
addSerialNumber(binding.serialNumberEd.text.toString())
}
}
val qrCode =
QRCodeOnboardingPayloadGenerator(onBoardingPayload)
.payloadBase38RepresentationWithAutoTLVBuffer()
Log.d(TAG, "QR Code : $qrCode")
binding.qrCodeTv.text = qrCode
}

binding.showQRCodeUriBtn.setOnClickListener {
val qrCodeEncode = URLEncoder.encode(binding.qrCodeTv.text.toString(), "UTF-8")
val qrCodeUri = getString(R.string.chip_device_info_qrcode_uri, qrCodeEncode)
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(qrCodeUri))
startActivity(intent)
}
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
Expand All @@ -96,6 +168,7 @@ class CHIPDeviceDetailsFragment : Fragment() {
}

companion object {
private const val TAG = "CHIPDeviceDetailsFragment"
private const val ARG_DEVICE_INFO = "device_info"

@JvmStatic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
package com.google.chip.chiptool.setuppayloadscanner

import android.os.Parcelable
import android.util.Log
import kotlinx.parcelize.Parcelize
import matter.onboardingpayload.DiscoveryCapability
import matter.onboardingpayload.OnboardingPayload
import matter.onboardingpayload.OnboardingPayloadException

/** Class to hold the CHIP device information. */
@Parcelize
Expand All @@ -35,12 +37,40 @@ data class CHIPDeviceInfo(
val optionalQrCodeInfoMap: Map<Int, QrCodeInfo> = mapOf(),
val discoveryCapabilities: MutableSet<DiscoveryCapability> = mutableSetOf(),
val isShortDiscriminator: Boolean = false,
val serialNumber: String = "",
val ipAddress: String? = null,
val port: Int = 5540
) : Parcelable {

fun toSetupPayload(): OnboardingPayload {
val onboardingPayload =
OnboardingPayload(
version,
vendorId,
productId,
commissioningFlow,
discoveryCapabilities,
discriminator,
isShortDiscriminator,
setupPinCode
)
if (serialNumber.isNotEmpty()) {
onboardingPayload.addSerialNumber(serialNumber)
}
return onboardingPayload
}

companion object {
private const val TAG = "CHIPDeviceInfo"

fun fromSetupPayload(setupPayload: OnboardingPayload): CHIPDeviceInfo {
val serialNumber =
try {
setupPayload.getSerialNumber()
} catch (e: OnboardingPayloadException) {
Log.d(TAG, "serialNumber Exception", e)
""
}
return CHIPDeviceInfo(
setupPayload.version,
setupPayload.vendorId,
Expand All @@ -52,7 +82,8 @@ data class CHIPDeviceInfo(
QrCodeInfo(info.tag, info.type, info.data, info.int32)
},
setupPayload.discoveryCapabilities,
setupPayload.hasShortDiscriminator
setupPayload.hasShortDiscriminator,
serialNumber
)
}
}
Expand Down
Loading

0 comments on commit 93aa97d

Please sign in to comment.