diff --git a/app/src/main/java/com/geeksville/mesh/model/UIState.kt b/app/src/main/java/com/geeksville/mesh/model/UIState.kt index 63e569ba0..fe4175e9b 100644 --- a/app/src/main/java/com/geeksville/mesh/model/UIState.kt +++ b/app/src/main/java/com/geeksville/mesh/model/UIState.kt @@ -124,12 +124,7 @@ class UIViewModel(private val app: Application) : AndroidViewModel(app), Logging } var lsSleepSecs: Int? - get() { - radioConfig.value?.preferences?.let { - return it.lsSecs - } - return null - } + get() = radioConfig.value?.preferences?.lsSecs set(value) { val config = radioConfig.value if (value != null && config != null) { @@ -139,6 +134,17 @@ class UIViewModel(private val app: Application) : AndroidViewModel(app), Logging } } + var region: RadioConfigProtos.RegionCode? + get() = radioConfig.value?.preferences?.region + set(value) { + val config = radioConfig.value + if (value != null && config != null) { + val builder = config.toBuilder() + builder.preferencesBuilder.region = value + setRadioConfig(builder.build()) + } + } + /// hardware info about our local device (can be null) val myNodeInfo = object : MutableLiveData(null) {} diff --git a/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt b/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt index 699734070..7c76458e5 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt @@ -40,24 +40,31 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi } private fun handleAdminPacket(pr: MeshProtos.ToRadio, d: AdminProtos.AdminMessage) { - if (d.getRadioRequest) - sendAdmin(pr.packet.to, pr.packet.from, pr.packet.id) { - getRadioResponse = RadioConfigProtos.RadioConfig.newBuilder().apply { + when { + d.getRadioRequest -> + sendAdmin(pr.packet.to, pr.packet.from, pr.packet.id) { + getRadioResponse = RadioConfigProtos.RadioConfig.newBuilder().apply { - preferences = RadioConfigProtos.RadioConfig.UserPreferences.newBuilder().apply { - region = RadioConfigProtos.RegionCode.TW - // FIXME set critical times? + preferences = + RadioConfigProtos.RadioConfig.UserPreferences.newBuilder().apply { + region = RadioConfigProtos.RegionCode.TW + // FIXME set critical times? + }.build() }.build() - }.build() - } + } - if (d.getChannelRequest != 0) - sendAdmin(pr.packet.to, pr.packet.from, pr.packet.id) { - getChannelResponse = ChannelProtos.Channel.newBuilder().apply { + d.getChannelRequest != 0 -> + sendAdmin(pr.packet.to, pr.packet.from, pr.packet.id) { + getChannelResponse = ChannelProtos.Channel.newBuilder().apply { index = d.getChannelRequest - 1 // 0 based on the response - role = if(d.getChannelRequest == 1) ChannelProtos.Channel.Role.PRIMARY else ChannelProtos.Channel.Role.DISABLED + role = + if (d.getChannelRequest == 1) ChannelProtos.Channel.Role.PRIMARY else ChannelProtos.Channel.Role.DISABLED }.build() - } + } + + else -> + info("Ignoring admin sent to mock interface $d") + } } override fun close() { diff --git a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt index 89db0be82..24f84fb4c 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt @@ -33,6 +33,7 @@ import com.geeksville.android.hideKeyboard import com.geeksville.android.isGooglePlayAvailable import com.geeksville.mesh.MainActivity import com.geeksville.mesh.R +import com.geeksville.mesh.RadioConfigProtos import com.geeksville.mesh.android.bluetoothManager import com.geeksville.mesh.android.usbManager import com.geeksville.mesh.databinding.SettingsFragmentBinding @@ -564,14 +565,37 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { } } - private fun initNodeInfo() { + /** + * Pull the latest device info from the model and into the GUI + */ + private fun updateNodeInfo() { val connected = model.isConnected.value - refreshUpdateButton() + val isConnected = connected == MeshService.ConnectionState.CONNECTED + binding.nodeSettings.visibility = if(isConnected) View.VISIBLE else View.GONE + + if (connected == MeshService.ConnectionState.DISCONNECTED) + model.ownerName.value = "" + + // update the region selection from the device + val region = model.region + if(region != null) { + val spinner = binding.regionSpinner + var regionIndex = regions.indexOf(region.name) + if(regionIndex == -1) // Not found, probably because the device has a region our app doesn't yet understand. Punt and say Unset + regionIndex = regions.indexOf(RadioConfigProtos.RegionCode.Unset.name) + + // We don't want to be notified of our own changes, so turn off listener while making them + spinner.onItemSelectedListener = null + spinner.setSelection(regionIndex, false) + spinner.onItemSelectedListener = regionSpinnerListener + } // If actively connected possibly let the user update firmware - val info = model.myNodeInfo.value + refreshUpdateButton() + // Update the status string + val info = model.myNodeInfo.value when (connected) { MeshService.ConnectionState.CONNECTED -> { val fwStr = info?.firmwareString ?: "" @@ -591,25 +615,33 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { position: Int, id: Long ) { - val item = parent.getItemAtPosition(position) - //TODO("Not yet implemented") + val item = parent.getItemAtPosition(position) as String + val asProto = item!!.let { RadioConfigProtos.RegionCode.valueOf(it) } + exceptionToSnackbar(requireView()) { + model.region = asProto + } } - override fun onNothingSelected(parent: AdapterView<*>?) { + override fun onNothingSelected(parent: AdapterView<*>) { //TODO("Not yet implemented") } } + /// the sorted list of region names + private val regions = RadioConfigProtos.RegionCode.values().filter { + it != RadioConfigProtos.RegionCode.UNRECOGNIZED + }.map { + it.name + }.sorted() + /// Setup the ui widgets unrelated to BLE scanning private fun initCommonUI() { - val regions = arrayOf("US", "CN", "EU488") + // val regions = arrayOf("US", "CN", "EU488") val spinner = binding.regionSpinner val regionAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, regions) regionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - // spinner.adapter = regionAdapter - - spinner.onItemSelectedListener = regionSpinnerListener + spinner.adapter = regionAdapter model.ownerName.observe(viewLifecycleOwner, { name -> binding.usernameEditText.setText(name) @@ -618,18 +650,12 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { // Only let user edit their name or set software update while connected to a radio model.isConnected.observe(viewLifecycleOwner, Observer { connectionState -> - val connected = connectionState == MeshService.ConnectionState.CONNECTED - binding.nodeSettings.visibility = if(connected) View.VISIBLE else View.GONE - - if (connectionState == MeshService.ConnectionState.DISCONNECTED) - model.ownerName.value = "" - - initNodeInfo() + updateNodeInfo() }) // Also watch myNodeInfo because it might change later model.myNodeInfo.observe(viewLifecycleOwner, Observer { - initNodeInfo() + updateNodeInfo() }) binding.updateFirmwareButton.setOnClickListener {