update protobufs

pull/435/head
andrekir 2022-05-26 16:23:47 -03:00
rodzic 60f6e0a96f
commit 48fd657d8a
15 zmienionych plików z 140 dodań i 150 usunięć

Wyświetl plik

@ -80,12 +80,12 @@ interface IMeshService {
List<DataPacket> getOldMessages();
/// This method is only intended for use in our GUI, so the user can set radio options
/// It returns a RadioConfig protobuf.
byte []getRadioConfig();
/// It returns a DeviceConfig protobuf.
byte []getDeviceConfig();
/// This method is only intended for use in our GUI, so the user can set radio options
/// It sets a RadioConfig protobuf
void setRadioConfig(in byte []payload);
/// It sets a DeviceConfig protobuf
void setDeviceConfig(in byte []payload);
/// This method is only intended for use in our GUI, so the user can set radio options
/// It returns a ChannelSet protobuf.

Wyświetl plik

@ -218,9 +218,6 @@ class MainActivity : BaseActivity(), Logging,
/** Ask the user to grant Bluetooth scan/discovery permission */
fun requestScanPermission() = requestPermission(getScanPermissions(), true)
/** Ask the user to grant camera permission */
fun requestCameraPermission() = requestPermission(getCameraPermissions())
/** Ask the user to grant foreground location permission */
fun requestLocationPermission() = requestPermission(getLocationPermissions())
@ -644,7 +641,7 @@ class MainActivity : BaseActivity(), Logging,
model.setConnectionState(newConnection)
debug("Getting latest radioconfig from service")
debug("Getting latest DeviceConfig from service")
try {
val info: MyNodeInfo? = service.myNodeInfo // this can be null
model.setMyNodeInfo(info)
@ -662,9 +659,9 @@ class MainActivity : BaseActivity(), Logging,
if (curVer < MeshService.minFirmwareVersion)
showAlert(R.string.firmware_too_old, R.string.firmware_old)
else {
// If our app is too old/new, we probably don't understand the new radioconfig messages, so we don't read them until here
// If our app is too old/new, we probably don't understand the new DeviceConfig messages, so we don't read them until here
model.setRadioConfig(RadioConfigProtos.RadioConfig.parseFrom(service.radioConfig))
model.setDeviceConfig(ConfigProtos.Config.parseFrom(service.deviceConfig))
model.setChannels(ChannelSet(AppOnlyProtos.ChannelSet.parseFrom(service.channels)))

Wyświetl plik

@ -22,7 +22,7 @@ data class Channel(val settings: ChannelProtos.ChannelSettings) {
// TH=he unsecured channel that devices ship with
val default = Channel(
ChannelProtos.ChannelSettings.newBuilder()
.setModemConfig(ChannelProtos.ChannelSettings.ModemConfig.LongFast)
// .setModemConfig(ChannelProtos.ChannelSettings.ModemConfig.LongFast)
.setPsk(ByteString.copyFrom(defaultPSK))
.build()
)
@ -30,26 +30,20 @@ data class Channel(val settings: ChannelProtos.ChannelSettings) {
/// Return the name of our channel as a human readable string. If empty string, assume "Default" per mesh.proto spec
val name: String
get() = if (settings.name.isEmpty()) {
// We have a new style 'empty' channel name. Use the same logic from the device to convert that to a human readable name
if (settings.bandwidth != 0)
"Unset"
else when (settings.modemConfig) {
ChannelProtos.ChannelSettings.ModemConfig.ShortFast -> "ShortFast"
ChannelProtos.ChannelSettings.ModemConfig.ShortSlow -> "ShortSlow"
ChannelProtos.ChannelSettings.ModemConfig.MidFast -> "MidFast"
ChannelProtos.ChannelSettings.ModemConfig.MidSlow -> "MidSlow"
ChannelProtos.ChannelSettings.ModemConfig.LongFast -> "LongFast"
ChannelProtos.ChannelSettings.ModemConfig.LongSlow -> "LongSlow"
ChannelProtos.ChannelSettings.ModemConfig.VLongSlow -> "VLongSlow"
get() = settings.name.ifEmpty { "Placeholder" /*
when (settings.modemConfig) {
ConfigProtos.Config.LoRaConfig.ModemPreset.ShortFast -> "ShortFast"
ConfigProtos.Config.LoRaConfig.ModemPreset.ShortSlow -> "ShortSlow"
ConfigProtos.Config.LoRaConfig.ModemPreset.MidFast -> "MidFast"
ConfigProtos.Config.LoRaConfig.ModemPreset.MidSlow -> "MidSlow"
ConfigProtos.Config.LoRaConfig.ModemPreset.LongFast -> "LongFast"
ConfigProtos.Config.LoRaConfig.ModemPreset.LongSlow -> "LongSlow"
ConfigProtos.Config.LoRaConfig.ModemPreset.VLongSlow -> "VLongSlow"
else -> "Invalid"
}
} else
settings.name
}*/
}
val modemConfig: ChannelProtos.ChannelSettings.ModemConfig get() = settings.modemConfig
val psk
val psk: ByteString
get() = if (settings.psk.size() != 1)
settings.psk // A standard PSK
else {
@ -86,4 +80,4 @@ data class Channel(val settings: ChannelProtos.ChannelSettings) {
&& name == o.name
}
fun xorHash(b: ByteArray) = b.fold(0, { acc, x -> acc xor (x.toInt() and 0xff) })
fun xorHash(b: ByteArray) = b.fold(0) { acc, x -> acc xor (x.toInt() and 0xff) }

Wyświetl plik

@ -1,25 +1,25 @@
package com.geeksville.mesh.model
import com.geeksville.mesh.ChannelProtos
import com.geeksville.mesh.ConfigProtos
import com.geeksville.mesh.R
enum class ChannelOption(
val modemConfig: ChannelProtos.ChannelSettings.ModemConfig,
val modemPreset: ConfigProtos.Config.LoRaConfig.ModemPreset,
val configRes: Int,
val minBroadcastPeriodSecs: Int
) {
SHORT_FAST(ChannelProtos.ChannelSettings.ModemConfig.ShortFast,R.string.modem_config_short, 30),
SHORT_SLOW(ChannelProtos.ChannelSettings.ModemConfig.ShortSlow, R.string.modem_config_slow_short, 30),
MED_FAST(ChannelProtos.ChannelSettings.ModemConfig.MidFast,R.string.modem_config_medium, 60),
MED_SLOW(ChannelProtos.ChannelSettings.ModemConfig.MidSlow,R.string.modem_config_slow_medium, 60),
LONG_FAST(ChannelProtos.ChannelSettings.ModemConfig.LongFast, R.string.modem_config_long, 240),
LONG_SLOW(ChannelProtos.ChannelSettings.ModemConfig.LongSlow, R.string.modem_config_slow_long, 375),
VERY_LONG(ChannelProtos.ChannelSettings.ModemConfig.VLongSlow, R.string.modem_config_very_long, 375);
SHORT_FAST(ConfigProtos.Config.LoRaConfig.ModemPreset.ShortFast, R.string.modem_config_short, 30),
SHORT_SLOW(ConfigProtos.Config.LoRaConfig.ModemPreset.ShortSlow, R.string.modem_config_slow_short, 30),
MED_FAST(ConfigProtos.Config.LoRaConfig.ModemPreset.MidFast, R.string.modem_config_medium, 60),
MED_SLOW(ConfigProtos.Config.LoRaConfig.ModemPreset.MidSlow, R.string.modem_config_slow_medium, 60),
LONG_FAST(ConfigProtos.Config.LoRaConfig.ModemPreset.LongFast, R.string.modem_config_long, 240),
LONG_SLOW(ConfigProtos.Config.LoRaConfig.ModemPreset.LongSlow, R.string.modem_config_slow_long, 375),
VERY_LONG(ConfigProtos.Config.LoRaConfig.ModemPreset.VLongSlow, R.string.modem_config_very_long, 375);
companion object {
fun fromConfig(modemConfig: ChannelProtos.ChannelSettings.ModemConfig?): ChannelOption? {
fun fromConfig(modemPreset: ConfigProtos.Config.LoRaConfig.ModemPreset?): ChannelOption? {
for (option in values()) {
if (option.modemConfig == modemConfig)
if (option.modemPreset == modemPreset)
return option
}
return null

Wyświetl plik

@ -22,8 +22,6 @@ data class ChannelSet(
private fun urlToChannels(url: Uri): AppOnlyProtos.ChannelSet {
val urlStr = url.toString()
// We no longer support the super old (about 0.8ish? verison of the URLs that don't use the # separator - I doubt
// anyone is still using that old format
val pathRegex = Regex("$prefix(.*)", RegexOption.IGNORE_CASE)
val (base64) = pathRegex.find(urlStr)?.destructured
?: throw MalformedURLException("Not a meshtastic URL: ${urlStr.take(40)}")
@ -51,13 +49,13 @@ data class ChannelSet(
/// Return an URL that represents the current channel values
/// @param upperCasePrefix - portions of the URL can be upper case to make for more efficient QR codes
fun getChannelUrl(upperCasePrefix: Boolean = false): Uri {
// If we have a valid radio config use it, othterwise use whatever we have saved in the prefs
// If we have a valid radio config use it, otherwise use whatever we have saved in the prefs
val channelBytes = protobuf.toByteArray() ?: ByteArray(0) // if unset just use empty
val enc = Base64.encodeToString(channelBytes, base64Flags)
val p = if (upperCasePrefix)
prefix.toUpperCase()
prefix.uppercase()
else
prefix
return Uri.parse("$p$enc")

Wyświetl plik

@ -43,8 +43,8 @@ fun getInitials(nameIn: String): String {
val words = name.split(Regex("\\s+")).filter { it.isNotEmpty() }
val initials = when (words.size) {
in 0..minchars - 1 -> {
val nm = if (name.length >= 1)
in 0 until minchars -> {
val nm = if (name.isNotEmpty())
name.first() + name.drop(1).filterNot { c -> c.lowercase() in "aeiou" }
else
""
@ -101,8 +101,8 @@ class UIViewModel @Inject constructor(
}
/// various radio settings (including the channel)
private val _radioConfig = MutableLiveData<RadioConfigProtos.RadioConfig?>()
val radioConfig: LiveData<RadioConfigProtos.RadioConfig?> get() = _radioConfig
private val _deviceConfig = MutableLiveData<ConfigProtos.Config?>()
val deviceConfig: LiveData<ConfigProtos.Config?> get() = _deviceConfig
private val _channels = MutableLiveData<ChannelSet?>()
val channels: LiveData<ChannelSet?> get() = _channels
@ -123,7 +123,7 @@ class UIViewModel @Inject constructor(
var positionBroadcastSecs: Int?
get() {
_radioConfig.value?.preferences?.let {
_deviceConfig.value?.position?.let {
if (it.positionBroadcastSecs > 0) return it.positionBroadcastSecs
// These default values are borrowed from the device code.
return 15 * 60
@ -131,50 +131,50 @@ class UIViewModel @Inject constructor(
return null
}
set(value) {
val config = _radioConfig.value
val config = _deviceConfig.value
if (value != null && config != null) {
val builder = config.toBuilder()
builder.preferencesBuilder.positionBroadcastSecs = value
setRadioConfig(builder.build())
builder.positionBuilder.positionBroadcastSecs = value
setDeviceConfig(builder.build())
}
}
var lsSleepSecs: Int?
get() = _radioConfig.value?.preferences?.lsSecs
get() = _deviceConfig.value?.power?.lsSecs
set(value) {
val config = _radioConfig.value
val config = _deviceConfig.value
if (value != null && config != null) {
val builder = config.toBuilder()
builder.preferencesBuilder.lsSecs = value
setRadioConfig(builder.build())
builder.powerBuilder.lsSecs = value
setDeviceConfig(builder.build())
}
}
var locationShareDisabled: Boolean
get() = _radioConfig.value?.preferences?.locationShareDisabled ?: false
var gpsDisabled: Boolean
get() = _deviceConfig.value?.position?.gpsDisabled ?: false
set(value) {
val config = _radioConfig.value
val config = _deviceConfig.value
if (config != null) {
val builder = config.toBuilder()
builder.preferencesBuilder.locationShareDisabled = value
setRadioConfig(builder.build())
builder.positionBuilder.gpsDisabled = value
setDeviceConfig(builder.build())
}
}
var isPowerSaving: Boolean?
get() = _radioConfig.value?.preferences?.isPowerSaving
get() = _deviceConfig.value?.power?.isPowerSaving
set(value) {
val config = _radioConfig.value
val config = _deviceConfig.value
if (value != null && config != null) {
val builder = config.toBuilder()
builder.preferencesBuilder.isPowerSaving = value
setRadioConfig(builder.build())
builder.powerBuilder.isPowerSaving = value
setDeviceConfig(builder.build())
}
}
var region: RadioConfigProtos.RegionCode
get() = meshService?.region?.let { RadioConfigProtos.RegionCode.forNumber(it) }
?: RadioConfigProtos.RegionCode.Unset
var region: ConfigProtos.Config.LoRaConfig.RegionCode
get() = meshService?.region?.let { ConfigProtos.Config.LoRaConfig.RegionCode.forNumber(it) }
?: ConfigProtos.Config.LoRaConfig.RegionCode.Unset
set(value) {
meshService?.region = value.number
}
@ -216,10 +216,10 @@ class UIViewModel @Inject constructor(
val primaryChannel: Channel? get() = _channels.value?.primaryChannel
// Set the radio config (also updates our saved copy in preferences)
fun setRadioConfig(c: RadioConfigProtos.RadioConfig) {
fun setDeviceConfig(c: ConfigProtos.Config) {
debug("Setting new radio config!")
meshService?.radioConfig = c.toByteArray()
_radioConfig.value =
meshService?.deviceConfig = c.toByteArray()
_deviceConfig.value =
c // Must be done after calling the service, so we will will properly throw if the service failed (and therefore not cache invalid new settings)
}

Wyświetl plik

@ -60,13 +60,13 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi
private fun handleAdminPacket(pr: MeshProtos.ToRadio, d: AdminProtos.AdminMessage) {
when {
d.getRadioRequest ->
d.getConfigRequest == AdminProtos.AdminMessage.ConfigType.LORA_CONFIG ->
sendAdmin(pr.packet.to, pr.packet.from, pr.packet.id) {
getRadioResponse = RadioConfigProtos.RadioConfig.newBuilder().apply {
getConfigResponse = ConfigProtos.Config.newBuilder().apply {
preferences =
RadioConfigProtos.RadioConfig.UserPreferences.newBuilder().apply {
region = RadioConfigProtos.RegionCode.TW
lora =
ConfigProtos.Config.LoRaConfig.newBuilder().apply {
region = ConfigProtos.Config.LoRaConfig.RegionCode.TW
// FIXME set critical times?
}.build()
}.build()

Wyświetl plik

@ -83,7 +83,7 @@ class MeshService : Service(), Logging {
class NodeNumNotFoundException(id: Int) : NodeNotFoundException("NodeNum not found $id")
class IdNotFoundException(id: String) : NodeNotFoundException("ID not found $id")
class NoRadioConfigException(message: String = "No radio settings received (is our app too old?)") :
class NoDeviceConfigException(message: String = "No radio settings received (is our app too old?)") :
RadioNotConnectedException(message)
/** We treat software update as similar to loss of comms to the regular bluetooth service (so things like sendPosition for background GPS ignores the problem */
@ -128,7 +128,7 @@ class MeshService : Service(), Logging {
private var locationFlow: Job? = null
// If we've ever read a valid region code from our device it will be here
var curRegionValue = RadioConfigProtos.RegionCode.Unset_VALUE
var curRegionValue = ConfigProtos.Config.LoRaConfig.RegionCode.Unset_VALUE
private fun getSenderName(packet: DataPacket?): String {
val name = nodeDBbyID[packet?.from]?.user?.longName
@ -350,7 +350,7 @@ class MeshService : Service(), Logging {
var myNodeInfo: MyNodeInfo? = null
private var radioConfig: RadioConfigProtos.RadioConfig? = null
private var deviceConfig: ConfigProtos.Config? = null
private var channels = fixupChannelList(listOf())
@ -725,9 +725,9 @@ class MeshService : Service(), Logging {
// For the time being we only care about admin messages from our local node
if (fromNodeNum == myNodeNum) {
when (a.variantCase) {
AdminProtos.AdminMessage.VariantCase.GET_RADIO_RESPONSE -> {
debug("Admin: received radioConfig")
radioConfig = a.getRadioResponse
AdminProtos.AdminMessage.VariantCase.GET_CONFIG_RESPONSE -> {
debug("Admin: received deviceConfig")
deviceConfig = a.getConfigResponse
requestChannel(0) // Now start reading channels
}
@ -983,7 +983,7 @@ class MeshService : Service(), Logging {
sleepTimeout = serviceScope.handledLaunch {
try {
// If we have a valid timeout, wait that long (+30 seconds) otherwise, just wait 30 seconds
val timeout = (radioConfig?.preferences?.lsSecs ?: 0) + 30
val timeout = (deviceConfig?.power?.lsSecs ?: 0) + 30
debug("Waiting for sleeping device, timeout=$timeout secs")
delay(timeout * 1000L)
@ -1075,7 +1075,7 @@ class MeshService : Service(), Logging {
private fun onRadioConnectionState(state: RadioServiceConnectionState) {
// sleep now disabled by default on ESP32, permanent is true unless isPowerSaving enabled
val lsEnabled = radioConfig?.preferences?.isPowerSaving ?: false
val lsEnabled = deviceConfig?.power?.isPowerSaving ?: false
val connected = state.isConnected
val permanent = state.isPermanent || !lsEnabled
onConnectionChanged(
@ -1105,7 +1105,7 @@ class MeshService : Service(), Logging {
MeshProtos.FromRadio.NODE_INFO_FIELD_NUMBER -> handleNodeInfo(proto.nodeInfo)
// MeshProtos.FromRadio.RADIO_FIELD_NUMBER -> handleRadioConfig(proto.radio)
// MeshProtos.FromRadio.RADIO_FIELD_NUMBER -> handleDeviceConfig(proto.radio)
else -> errormsg("Unexpected FromRadio variant")
}
@ -1249,7 +1249,7 @@ class MeshService : Service(), Logging {
regenMyNodeInfo()
// We'll need to get a new set of channels and settings now
radioConfig = null
deviceConfig = null
// prefill the channel array with null channels
channels = fixupChannelList(listOf<ChannelProtos.Channel>())
@ -1272,21 +1272,21 @@ class MeshService : Service(), Logging {
private fun setRegionOnDevice() {
val curConfigRegion =
radioConfig?.preferences?.region ?: RadioConfigProtos.RegionCode.Unset
deviceConfig?.lora?.region ?: ConfigProtos.Config.LoRaConfig.RegionCode.Unset
if (curConfigRegion.number != curRegionValue && curRegionValue != RadioConfigProtos.RegionCode.Unset_VALUE)
if (curConfigRegion.number != curRegionValue && curRegionValue != ConfigProtos.Config.LoRaConfig.RegionCode.Unset_VALUE)
if (deviceVersion >= minFirmwareVersion) {
info("Telling device to upgrade region")
// Tell the device to set the new region field (old devices will simply ignore this)
radioConfig?.let { currentConfig ->
deviceConfig?.let { currentConfig ->
val newConfig = currentConfig.toBuilder()
val newPrefs = currentConfig.preferences.toBuilder()
val newPrefs = currentConfig.lora.toBuilder()
newPrefs.regionValue = curRegionValue
newConfig.preferences = newPrefs.build()
newConfig.lora = newPrefs.build()
sendRadioConfig(newConfig.build())
sendDeviceConfig(newConfig.build())
}
} else
warn("Device is too old to understand region changes")
@ -1301,8 +1301,8 @@ class MeshService : Service(), Logging {
// Try to pull our region code from the new preferences field
// FIXME - do not check net - figuring out why board is rebooting
val curConfigRegion =
radioConfig?.preferences?.region ?: RadioConfigProtos.RegionCode.Unset
if (curConfigRegion != RadioConfigProtos.RegionCode.Unset) {
deviceConfig?.lora?.region ?: ConfigProtos.Config.LoRaConfig.RegionCode.Unset
if (curConfigRegion != ConfigProtos.Config.LoRaConfig.RegionCode.Unset) {
info("Using device region $curConfigRegion (code ${curConfigRegion.number})")
curRegionValue = curConfigRegion.number
}
@ -1357,15 +1357,15 @@ class MeshService : Service(), Logging {
info("Device firmware is too old, faking config so firmware update can occur")
onHasSettings()
} else
requestRadioConfig()
requestDeviceConfig()
}
} else
warn("Ignoring stale config complete")
}
private fun requestRadioConfig() {
private fun requestDeviceConfig() {
sendToRadio(newMeshPacketTo(myNodeNum).buildAdminPacket(wantResponse = true) {
getRadioRequest = true
getConfigRequest = AdminProtos.AdminMessage.ConfigType.DEVICE_CONFIG
})
}
@ -1440,22 +1440,22 @@ class MeshService : Service(), Logging {
/** Send our current radio config to the device
*/
private fun sendRadioConfig(c: RadioConfigProtos.RadioConfig) {
private fun sendDeviceConfig(c: ConfigProtos.Config) {
// send the packet into the mesh
sendToRadio(newMeshPacketTo(myNodeNum).buildAdminPacket {
setRadio = c
setConfig = c
})
// Update our cached copy
this@MeshService.radioConfig = c
this@MeshService.deviceConfig = c
}
/** Set our radio config
*/
private fun setRadioConfig(payload: ByteArray) {
val parsed = RadioConfigProtos.RadioConfig.parseFrom(payload)
private fun setDeviceConfig(payload: ByteArray) {
val parsed = ConfigProtos.Config.parseFrom(payload)
sendRadioConfig(parsed)
sendDeviceConfig(parsed)
}
/**
@ -1690,13 +1690,13 @@ class MeshService : Service(), Logging {
}
}
override fun getRadioConfig(): ByteArray = toRemoteExceptions {
this@MeshService.radioConfig?.toByteArray()
?: throw NoRadioConfigException()
override fun getDeviceConfig(): ByteArray = toRemoteExceptions {
this@MeshService.deviceConfig?.toByteArray()
?: throw NoDeviceConfigException()
}
override fun setRadioConfig(payload: ByteArray) = toRemoteExceptions {
this@MeshService.setRadioConfig(payload)
override fun setDeviceConfig(payload: ByteArray) = toRemoteExceptions {
this@MeshService.setDeviceConfig(payload)
}
override fun getChannels(): ByteArray = toRemoteExceptions {

Wyświetl plik

@ -3,7 +3,7 @@ package com.geeksville.mesh.service
import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.MyNodeInfo
import com.geeksville.mesh.NodeInfo
import com.geeksville.mesh.RadioConfigProtos
import com.geeksville.mesh.ConfigProtos
import kotlinx.serialization.Serializable
/// Our saved preferences as stored on disk
@ -12,7 +12,7 @@ data class MeshServiceSettingsData(
val nodeDB: Array<NodeInfo>,
val myInfo: MyNodeInfo,
val messages: Array<DataPacket>,
val regionCode: Int = RadioConfigProtos.RegionCode.Unset_VALUE
val regionCode: Int = ConfigProtos.Config.LoRaConfig.RegionCode.Unset_VALUE
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true

Wyświetl plik

@ -37,18 +37,18 @@ class AdvancedSettingsFragment : ScreenFragment("Advanced Settings"), Logging {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model.radioConfig.observe(viewLifecycleOwner) {
model.deviceConfig.observe(viewLifecycleOwner) {
binding.positionBroadcastPeriodEditText.setText(model.positionBroadcastSecs.toString())
binding.lsSleepEditText.setText(model.lsSleepSecs.toString())
binding.positionBroadcastPeriodView.isEnabled = !model.locationShareDisabled
binding.positionBroadcastSwitch.isChecked = !model.locationShareDisabled
binding.positionBroadcastPeriodView.isEnabled = !model.gpsDisabled
binding.positionBroadcastSwitch.isChecked = !model.gpsDisabled
binding.lsSleepView.isEnabled = model.isPowerSaving ?: false
binding.lsSleepSwitch.isChecked = model.isPowerSaving ?: false
}
model.connectionState.observe(viewLifecycleOwner) { connectionState ->
val connected = connectionState == MeshService.ConnectionState.CONNECTED
binding.positionBroadcastPeriodView.isEnabled = connected && !model.locationShareDisabled
binding.positionBroadcastPeriodView.isEnabled = connected && !model.gpsDisabled
binding.lsSleepView.isEnabled = connected && model.isPowerSaving ?: false
binding.positionBroadcastSwitch.isEnabled = connected
binding.lsSleepSwitch.isEnabled = connected
@ -58,7 +58,7 @@ class AdvancedSettingsFragment : ScreenFragment("Advanced Settings"), Logging {
val textEdit = binding.positionBroadcastPeriodEditText
val n = textEdit.text.toString().toIntOrNull()
val minBroadcastPeriodSecs =
ChannelOption.fromConfig(model.primaryChannel?.modemConfig)?.minBroadcastPeriodSecs
ChannelOption.fromConfig(model.deviceConfig.value?.lora?.modemPreset)?.minBroadcastPeriodSecs
?: ChannelOption.defaultMinBroadcastPeriod
if (n != null && n < MAX_INT_DEVICE && (n == 0 || n >= minBroadcastPeriodSecs)) {
@ -81,7 +81,7 @@ class AdvancedSettingsFragment : ScreenFragment("Advanced Settings"), Logging {
binding.positionBroadcastSwitch.setOnCheckedChangeListener { view, isChecked ->
if (view.isPressed) {
model.locationShareDisabled = !isChecked
model.gpsDisabled = !isChecked
debug("User changed locationShare to $isChecked")
}
}

Wyświetl plik

@ -23,6 +23,7 @@ import com.geeksville.android.hideKeyboard
import com.geeksville.android.isGooglePlayAvailable
import com.geeksville.mesh.AppOnlyProtos
import com.geeksville.mesh.ChannelProtos
import com.geeksville.mesh.ConfigProtos
import com.geeksville.mesh.R
import com.geeksville.mesh.android.hasCameraPermission
import com.geeksville.mesh.databinding.ChannelFragmentBinding
@ -107,15 +108,15 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
binding.channelNameEdit.setText(channel.humanName)
// For now, we only let the user edit/save channels while the radio is awake - because the service
// doesn't cache radioconfig writes.
// doesn't cache DeviceConfig writes.
binding.editableCheckbox.isEnabled = connected
val bitmap = channels.qrCode
if (bitmap != null)
binding.qrView.setImageBitmap(bitmap)
val modemConfig = channel.modemConfig
val channelOption = ChannelOption.fromConfig(modemConfig)
val modemPreset = model.deviceConfig.value?.lora?.modemPreset
val channelOption = ChannelOption.fromConfig(modemPreset)
binding.filledExposedDropdown.setText(
getString(
channelOption?.configRes ?: R.string.modem_config_unrecognized
@ -128,12 +129,12 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
binding.editableCheckbox.isEnabled = false
}
val modemConfigs = ChannelOption.values()
val modemConfigList = modemConfigs.map { getString(it.configRes) }
val modemPresets = ChannelOption.values()
val modemPresetList = modemPresets.map { getString(it.configRes) }
val adapter = ArrayAdapter(
requireContext(),
R.layout.dropdown_menu_popup_item,
modemConfigList
modemPresetList
)
binding.filledExposedDropdown.setAdapter(adapter)
@ -174,10 +175,10 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
private fun installSettings(newChannel: ChannelProtos.ChannelSettings) {
val newSet =
ChannelSet(AppOnlyProtos.ChannelSet.newBuilder().addSettings(newChannel).build())
// Try to change the radio, if it fails, tell the user why and throw away their redits
// Try to change the radio, if it fails, tell the user why and throw away their edits
try {
model.setChannels(newSet)
// Since we are writing to radioconfig, that will trigger the rest of the GUI update (QR code etc)
// Since we are writing to DeviceConfig, that will trigger the rest of the GUI update (QR code etc)
} catch (ex: RemoteException) {
errormsg("ignoring channel problem", ex)
@ -282,7 +283,7 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
if (checked) {
// User just unlocked for editing - remove the # goo around the channel name
model.channels.value?.primaryChannel?.let { ch ->
// Note: We are careful to show the emptystring here if the user was on a default channel, so the user knows they should it for any changes
// Note: We are careful to show the empty string here if the user was on a default channel, so the user knows they should it for any changes
originalName = ch.settings.name
binding.channelNameEdit.setText(originalName)
}
@ -303,18 +304,20 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
// Find the new modem config
val selectedChannelOptionString =
binding.filledExposedDropdown.editableText.toString()
var modemConfig = getModemConfig(selectedChannelOptionString)
if (modemConfig == ChannelProtos.ChannelSettings.ModemConfig.UNRECOGNIZED) // Huh? didn't find it - keep same
modemConfig = oldPrimary.settings.modemConfig
var modemPreset = getModemPreset(selectedChannelOptionString)
// if (modemPreset == ConfigProtos.Config.LoRaConfig.ModemPreset.UNRECOGNIZED) // Huh? didn't find it - keep same
// modemPreset = oldPrimary.settings.modemConfig -> TODO add from LoraConfig.ModemPreset?
// Generate a new AES256 key if the user changes channel name or the name is non-default and the settings changed
if (newName != originalName || (newName.isNotEmpty() && modemConfig != oldPrimary.settings.modemConfig)) {
// if (newName != originalName || (newName.isNotEmpty() && modemConfig != oldPrimary.settings.modemConfig)) {
if (newName != originalName || newName.isNotEmpty()) {
// Install a new customized channel
debug("ASSIGNING NEW AES256 KEY")
val random = SecureRandom()
val bytes = ByteArray(32)
random.nextBytes(bytes)
newSettings.name = newName
newSettings.name = newName.take(11) // proto max_size:12
newSettings.psk = ByteString.copyFrom(bytes)
} else {
debug("Switching back to default channel")
@ -322,7 +325,7 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
}
// No matter what apply the speed selection from the user
newSettings.modemConfig = modemConfig
// newSettings.modemConfig = modemPreset -> TODO add from LoraConfig.ModemPreset?
installSettings(newSettings.build())
}
@ -348,12 +351,12 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
}
}
private fun getModemConfig(selectedChannelOptionString: String): ChannelProtos.ChannelSettings.ModemConfig {
private fun getModemPreset(selectedChannelOptionString: String): ConfigProtos.Config.LoRaConfig.ModemPreset {
for (item in ChannelOption.values()) {
if (getString(item.configRes) == selectedChannelOptionString)
return item.modemConfig
return item.modemPreset
}
return ChannelProtos.ChannelSettings.ModemConfig.UNRECOGNIZED
return ConfigProtos.Config.LoRaConfig.ModemPreset.UNRECOGNIZED
}
private val requestPermissionAndScanLauncher =

Wyświetl plik

@ -87,7 +87,7 @@ class ContactsFragment : ScreenFragment("Messages"), Logging {
val nodes = model.nodeDB.nodes.value!!
val node = nodes[if (isLocal) contact.to else contact.from]
//grab channel names from RadioConfig
//grab channel names from DeviceConfig
val channels = model.channels.value
val primaryChannel = channels?.primaryChannel

Wyświetl plik

@ -296,9 +296,6 @@ class MessagesFragment : Fragment(), Logging {
val connected = connectionState == MeshService.ConnectionState.CONNECTED
binding.textInputLayout.isEnabled = connected
binding.sendButton.isEnabled = connected
// Just being connected is enough to allow sending texts I think
// && model.nodeDB.myId.value != null && model.radioConfig.value != null
}
}

Wyświetl plik

@ -32,7 +32,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.ConfigProtos
import com.geeksville.mesh.android.*
import com.geeksville.mesh.databinding.SettingsFragmentBinding
import com.geeksville.mesh.model.BluetoothViewModel
@ -659,7 +659,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
// update the region selection from the device
val region = model.region
val spinner = binding.regionSpinner
val unsetIndex = regions.indexOf(RadioConfigProtos.RegionCode.Unset.name)
val unsetIndex = regions.indexOf(ConfigProtos.Config.LoRaConfig.RegionCode.Unset.name)
spinner.onItemSelectedListener = null
debug("current region is $region")
@ -673,7 +673,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
spinner.isEnabled = true
// If actively connected possibly let the user update firmware
refreshUpdateButton(region != RadioConfigProtos.RegionCode.Unset)
refreshUpdateButton(region != ConfigProtos.Config.LoRaConfig.RegionCode.Unset)
// Update the status string (highest priority messages first)
val info = model.myNodeInfo.value
@ -683,7 +683,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
(permissionsWarning != null) ->
statusText.text = permissionsWarning
region == RadioConfigProtos.RegionCode.Unset ->
region == ConfigProtos.Config.LoRaConfig.RegionCode.Unset ->
statusText.text = getString(R.string.must_set_region)
connected == MeshService.ConnectionState.CONNECTED -> {
@ -705,7 +705,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
id: Long
) {
val item = parent.getItemAtPosition(position) as String?
val asProto = item!!.let { RadioConfigProtos.RegionCode.valueOf(it) }
val asProto = item!!.let { ConfigProtos.Config.LoRaConfig.RegionCode.valueOf(it) }
exceptionToSnackbar(requireView()) {
model.region = asProto
}
@ -718,8 +718,8 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
}
/// the sorted list of region names like arrayOf("US", "CN", "EU488")
private val regions = RadioConfigProtos.RegionCode.values().filter {
it != RadioConfigProtos.RegionCode.UNRECOGNIZED
private val regions = ConfigProtos.Config.LoRaConfig.RegionCode.values().filter {
it != ConfigProtos.Config.LoRaConfig.RegionCode.UNRECOGNIZED
}.map {
it.name
}.sorted()
@ -746,10 +746,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
updateDevicesButtons(scanModel.devices.value)
}
model.radioConfig.observe(viewLifecycleOwner) {
model.deviceConfig.observe(viewLifecycleOwner) {
binding.provideLocationCheckbox.isEnabled =
isGooglePlayAvailable(requireContext()) && !model.locationShareDisabled
if (model.locationShareDisabled) {
isGooglePlayAvailable(requireContext()) && !model.gpsDisabled
if (model.gpsDisabled) {
model.provideLocation.value = false
binding.provideLocationCheckbox.isChecked = false
}

Wyświetl plik

@ -13,6 +13,8 @@
android:layout_marginTop="16dp"
android:layout_marginEnd="64dp"
android:hint="@string/channel_name"
app:counterEnabled="true"
app:counterMaxLength="11"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
@ -23,7 +25,6 @@
android:layout_height="wrap_content"
android:digits="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890- "
android:imeOptions="actionDone"
android:maxLength="15"
android:singleLine="true"
android:text="@string/unset" />
</com.google.android.material.textfield.TextInputLayout>