| package com.google.chip.chiptool.provisioning |
| |
| import android.content.BroadcastReceiver |
| import android.content.Context |
| import android.content.Intent |
| import android.content.IntentFilter |
| import android.net.wifi.WifiManager |
| import android.net.wifi.ScanResult |
| import android.net.wifi.WifiConfiguration |
| import android.os.Bundle |
| import android.util.Log |
| import android.view.LayoutInflater |
| import android.view.View |
| import android.view.ViewGroup |
| import android.widget.AdapterView |
| import android.widget.ArrayAdapter |
| import androidx.fragment.app.Fragment |
| import com.google.chip.chiptool.ChipClient |
| import com.google.chip.chiptool.databinding.AddressCommissioningFragmentBinding |
| import com.google.chip.chiptool.setuppayloadscanner.BarcodeFragment |
| import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceInfo |
| import com.google.chip.chiptool.util.FragmentUtil |
| import kotlinx.coroutines.CoroutineScope |
| import kotlinx.coroutines.Dispatchers |
| import kotlinx.coroutines.Job |
| import kotlinx.coroutines.delay |
| import kotlinx.coroutines.launch |
| |
| class AddressCommissioningFragment : Fragment() { |
| private val ipAddressList = ArrayList<String>() |
| private val wifiApList = ArrayList<String>() |
| private var wifiApSsid = String() |
| private val scope = CoroutineScope(Dispatchers.Main + Job()) |
| private var _binding: AddressCommissioningFragmentBinding? = null |
| private val binding get() = _binding!! |
| |
| override fun onCreateView( |
| inflater: LayoutInflater, |
| container: ViewGroup?, |
| savedInstanceState: Bundle? |
| ): View { |
| _binding = AddressCommissioningFragmentBinding.inflate(inflater, container, false) |
| return binding.root |
| } |
| |
| override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| super.onViewCreated(view, savedInstanceState) |
| |
| binding.commissionBtn.setOnClickListener { |
| val address = binding.addressEditText.text.toString() |
| val discriminator = binding.discriminatorEditText.text.toString() |
| val pincode = binding.pincodeEditText.text.toString() |
| |
| if (address.isEmpty() || discriminator.isEmpty() || pincode.isEmpty()) { |
| Log.e(TAG, "Address, discriminator, or pincode was empty: $address $discriminator $pincode") |
| return@setOnClickListener |
| } |
| |
| FragmentUtil.getHost(this, BarcodeFragment.Callback::class.java)?.onCHIPDeviceInfoReceived( |
| CHIPDeviceInfo( |
| discriminator = discriminator.toInt(), |
| setupPinCode = pincode.toLong(), |
| ipAddress = address |
| ) |
| ) |
| } |
| |
| binding.discoverBtn.setOnClickListener { _ -> |
| binding.discoverBtn.isEnabled = false |
| val deviceController = ChipClient.getDeviceController(requireContext()) |
| deviceController.discoverCommissionableNodes() |
| scope.launch { |
| delay(7000) |
| updateSpinner() |
| binding.discoverBtn.isEnabled = true |
| } |
| } |
| |
| binding.wifiConnectBtn.setOnClickListener { _ -> |
| binding.wifiConnectBtn.isEnabled = false |
| val context = getActivity() |
| val wifiManager = context?.getSystemService(Context.WIFI_SERVICE) as WifiManager |
| |
| // TODO : filter SSID with Information Element, OPEN authentication |
| var config : WifiConfiguration = WifiConfiguration(); |
| config.SSID = "\"${wifiApSsid}\"" |
| config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE) |
| |
| Log.d(TAG, "Disconnect existing connection") |
| wifiManager.disconnect() |
| Log.d(TAG, "Add network ${config.SSID}") |
| var res = wifiManager.addNetwork(config) |
| if (res == -1) { |
| Log.d(TAG,"Add network failed") |
| } else { |
| var success = wifiManager.enableNetwork(res, true) |
| if (success) { |
| Log.d(TAG, "Enable network ${config.SSID} succeeded") |
| } else { |
| Log.d(TAG, "Enable network ${config.SSID} failed") |
| binding.wifiConnectBtn.isEnabled = true |
| } |
| } |
| } |
| |
| binding.wifiScanBtn.setOnClickListener { _ -> |
| binding.wifiScanBtn.isEnabled = false |
| val context = getActivity() |
| val wifiManager = context?.getSystemService(Context.WIFI_SERVICE) as WifiManager |
| val wifiScanReceiver = object : BroadcastReceiver() { |
| override fun onReceive(context: Context, intent: Intent) { |
| Log.d(TAG, "Scan result event received") |
| val success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false) |
| if (success) { |
| Log.d(TAG, "Scan succeeded") |
| val results = wifiManager.scanResults |
| updateWifiScanListSpinner(results) |
| } else { |
| Log.d(TAG, "Scan failed") |
| } |
| binding.wifiScanBtn.isEnabled = true |
| } |
| } |
| |
| val intentFilter = IntentFilter() |
| intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) |
| |
| context.registerReceiver(wifiScanReceiver, intentFilter) |
| val success = wifiManager.startScan() |
| if (!success) { |
| Log.d(TAG, "Scan not started") |
| // TODO: scan failure handling |
| } else { |
| Log.d(TAG, "Scan started") |
| } |
| } |
| } |
| |
| override fun onDestroyView() { |
| super.onDestroyView() |
| _binding = null |
| } |
| |
| private fun updateWifiScanListSpinner(scanResults : MutableList<ScanResult>) { |
| wifiApList.clear() |
| for (result in scanResults) { |
| if (result.SSID.toString().isNotEmpty()) |
| wifiApList.add("${result.SSID}, ${result.BSSID}, ${result.level}") |
| } |
| requireActivity().runOnUiThread { |
| binding.wifiScanListSpinner.adapter = |
| ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, wifiApList) |
| binding.wifiScanListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { |
| override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { |
| wifiApSsid = wifiApList[position].split(",")[0].trim() |
| Log.d(TAG, "ready to connect to $wifiApSsid") |
| } |
| override fun onNothingSelected(parent: AdapterView<*>) {} |
| } |
| } |
| } |
| |
| private fun updateSpinner() { |
| val deviceController = ChipClient.getDeviceController(requireContext()) |
| for(i in 0..10) { |
| val device = deviceController.getDiscoveredDevice(i) ?: break |
| ipAddressList.add("${device.ipAddress}, ${device.discriminator}") |
| } |
| requireActivity().runOnUiThread { |
| binding.discoverListSpinner.adapter = |
| ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, ipAddressList) |
| binding.discoverListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { |
| override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { |
| val address = ipAddressList[position].split(",")[0].trim() |
| val discriminator = ipAddressList[position].split(",")[1].trim() |
| |
| binding.addressEditText.setText(address) |
| binding.discriminatorEditText.setText(discriminator) |
| } |
| |
| override fun onNothingSelected(parent: AdapterView<*>) {} |
| } |
| } |
| } |
| |
| companion object { |
| private const val TAG = "AddressCommissioningFragment" |
| |
| fun newInstance(): AddressCommissioningFragment = AddressCommissioningFragment() |
| } |
| } |