mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
update protobufs
This commit is contained in:
parent
60f6e0a96f
commit
48fd657d8a
15 changed files with 140 additions and 150 deletions
|
|
@ -80,12 +80,12 @@ interface IMeshService {
|
||||||
List<DataPacket> getOldMessages();
|
List<DataPacket> getOldMessages();
|
||||||
|
|
||||||
/// This method is only intended for use in our GUI, so the user can set radio options
|
/// This method is only intended for use in our GUI, so the user can set radio options
|
||||||
/// It returns a RadioConfig protobuf.
|
/// It returns a DeviceConfig protobuf.
|
||||||
byte []getRadioConfig();
|
byte []getDeviceConfig();
|
||||||
|
|
||||||
/// This method is only intended for use in our GUI, so the user can set radio options
|
/// This method is only intended for use in our GUI, so the user can set radio options
|
||||||
/// It sets a RadioConfig protobuf
|
/// It sets a DeviceConfig protobuf
|
||||||
void setRadioConfig(in byte []payload);
|
void setDeviceConfig(in byte []payload);
|
||||||
|
|
||||||
/// This method is only intended for use in our GUI, so the user can set radio options
|
/// This method is only intended for use in our GUI, so the user can set radio options
|
||||||
/// It returns a ChannelSet protobuf.
|
/// It returns a ChannelSet protobuf.
|
||||||
|
|
|
||||||
|
|
@ -218,9 +218,6 @@ class MainActivity : BaseActivity(), Logging,
|
||||||
/** Ask the user to grant Bluetooth scan/discovery permission */
|
/** Ask the user to grant Bluetooth scan/discovery permission */
|
||||||
fun requestScanPermission() = requestPermission(getScanPermissions(), true)
|
fun requestScanPermission() = requestPermission(getScanPermissions(), true)
|
||||||
|
|
||||||
/** Ask the user to grant camera permission */
|
|
||||||
fun requestCameraPermission() = requestPermission(getCameraPermissions())
|
|
||||||
|
|
||||||
/** Ask the user to grant foreground location permission */
|
/** Ask the user to grant foreground location permission */
|
||||||
fun requestLocationPermission() = requestPermission(getLocationPermissions())
|
fun requestLocationPermission() = requestPermission(getLocationPermissions())
|
||||||
|
|
||||||
|
|
@ -644,7 +641,7 @@ class MainActivity : BaseActivity(), Logging,
|
||||||
|
|
||||||
model.setConnectionState(newConnection)
|
model.setConnectionState(newConnection)
|
||||||
|
|
||||||
debug("Getting latest radioconfig from service")
|
debug("Getting latest DeviceConfig from service")
|
||||||
try {
|
try {
|
||||||
val info: MyNodeInfo? = service.myNodeInfo // this can be null
|
val info: MyNodeInfo? = service.myNodeInfo // this can be null
|
||||||
model.setMyNodeInfo(info)
|
model.setMyNodeInfo(info)
|
||||||
|
|
@ -662,9 +659,9 @@ class MainActivity : BaseActivity(), Logging,
|
||||||
if (curVer < MeshService.minFirmwareVersion)
|
if (curVer < MeshService.minFirmwareVersion)
|
||||||
showAlert(R.string.firmware_too_old, R.string.firmware_old)
|
showAlert(R.string.firmware_too_old, R.string.firmware_old)
|
||||||
else {
|
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)))
|
model.setChannels(ChannelSet(AppOnlyProtos.ChannelSet.parseFrom(service.channels)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ data class Channel(val settings: ChannelProtos.ChannelSettings) {
|
||||||
// TH=he unsecured channel that devices ship with
|
// TH=he unsecured channel that devices ship with
|
||||||
val default = Channel(
|
val default = Channel(
|
||||||
ChannelProtos.ChannelSettings.newBuilder()
|
ChannelProtos.ChannelSettings.newBuilder()
|
||||||
.setModemConfig(ChannelProtos.ChannelSettings.ModemConfig.LongFast)
|
// .setModemConfig(ChannelProtos.ChannelSettings.ModemConfig.LongFast)
|
||||||
.setPsk(ByteString.copyFrom(defaultPSK))
|
.setPsk(ByteString.copyFrom(defaultPSK))
|
||||||
.build()
|
.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
|
/// Return the name of our channel as a human readable string. If empty string, assume "Default" per mesh.proto spec
|
||||||
val name: String
|
val name: String
|
||||||
get() = if (settings.name.isEmpty()) {
|
get() = settings.name.ifEmpty { "Placeholder" /*
|
||||||
// We have a new style 'empty' channel name. Use the same logic from the device to convert that to a human readable name
|
when (settings.modemConfig) {
|
||||||
if (settings.bandwidth != 0)
|
ConfigProtos.Config.LoRaConfig.ModemPreset.ShortFast -> "ShortFast"
|
||||||
"Unset"
|
ConfigProtos.Config.LoRaConfig.ModemPreset.ShortSlow -> "ShortSlow"
|
||||||
else when (settings.modemConfig) {
|
ConfigProtos.Config.LoRaConfig.ModemPreset.MidFast -> "MidFast"
|
||||||
ChannelProtos.ChannelSettings.ModemConfig.ShortFast -> "ShortFast"
|
ConfigProtos.Config.LoRaConfig.ModemPreset.MidSlow -> "MidSlow"
|
||||||
ChannelProtos.ChannelSettings.ModemConfig.ShortSlow -> "ShortSlow"
|
ConfigProtos.Config.LoRaConfig.ModemPreset.LongFast -> "LongFast"
|
||||||
ChannelProtos.ChannelSettings.ModemConfig.MidFast -> "MidFast"
|
ConfigProtos.Config.LoRaConfig.ModemPreset.LongSlow -> "LongSlow"
|
||||||
ChannelProtos.ChannelSettings.ModemConfig.MidSlow -> "MidSlow"
|
ConfigProtos.Config.LoRaConfig.ModemPreset.VLongSlow -> "VLongSlow"
|
||||||
ChannelProtos.ChannelSettings.ModemConfig.LongFast -> "LongFast"
|
|
||||||
ChannelProtos.ChannelSettings.ModemConfig.LongSlow -> "LongSlow"
|
|
||||||
ChannelProtos.ChannelSettings.ModemConfig.VLongSlow -> "VLongSlow"
|
|
||||||
else -> "Invalid"
|
else -> "Invalid"
|
||||||
}
|
}*/
|
||||||
} else
|
}
|
||||||
settings.name
|
|
||||||
|
|
||||||
val modemConfig: ChannelProtos.ChannelSettings.ModemConfig get() = settings.modemConfig
|
val psk: ByteString
|
||||||
|
|
||||||
val psk
|
|
||||||
get() = if (settings.psk.size() != 1)
|
get() = if (settings.psk.size() != 1)
|
||||||
settings.psk // A standard PSK
|
settings.psk // A standard PSK
|
||||||
else {
|
else {
|
||||||
|
|
@ -86,4 +80,4 @@ data class Channel(val settings: ChannelProtos.ChannelSettings) {
|
||||||
&& name == o.name
|
&& 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) }
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
package com.geeksville.mesh.model
|
package com.geeksville.mesh.model
|
||||||
|
|
||||||
import com.geeksville.mesh.ChannelProtos
|
import com.geeksville.mesh.ConfigProtos
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
|
|
||||||
enum class ChannelOption(
|
enum class ChannelOption(
|
||||||
val modemConfig: ChannelProtos.ChannelSettings.ModemConfig,
|
val modemPreset: ConfigProtos.Config.LoRaConfig.ModemPreset,
|
||||||
val configRes: Int,
|
val configRes: Int,
|
||||||
val minBroadcastPeriodSecs: Int
|
val minBroadcastPeriodSecs: Int
|
||||||
) {
|
) {
|
||||||
SHORT_FAST(ChannelProtos.ChannelSettings.ModemConfig.ShortFast,R.string.modem_config_short, 30),
|
SHORT_FAST(ConfigProtos.Config.LoRaConfig.ModemPreset.ShortFast, R.string.modem_config_short, 30),
|
||||||
SHORT_SLOW(ChannelProtos.ChannelSettings.ModemConfig.ShortSlow, R.string.modem_config_slow_short, 30),
|
SHORT_SLOW(ConfigProtos.Config.LoRaConfig.ModemPreset.ShortSlow, R.string.modem_config_slow_short, 30),
|
||||||
MED_FAST(ChannelProtos.ChannelSettings.ModemConfig.MidFast,R.string.modem_config_medium, 60),
|
MED_FAST(ConfigProtos.Config.LoRaConfig.ModemPreset.MidFast, R.string.modem_config_medium, 60),
|
||||||
MED_SLOW(ChannelProtos.ChannelSettings.ModemConfig.MidSlow,R.string.modem_config_slow_medium, 60),
|
MED_SLOW(ConfigProtos.Config.LoRaConfig.ModemPreset.MidSlow, R.string.modem_config_slow_medium, 60),
|
||||||
LONG_FAST(ChannelProtos.ChannelSettings.ModemConfig.LongFast, R.string.modem_config_long, 240),
|
LONG_FAST(ConfigProtos.Config.LoRaConfig.ModemPreset.LongFast, R.string.modem_config_long, 240),
|
||||||
LONG_SLOW(ChannelProtos.ChannelSettings.ModemConfig.LongSlow, R.string.modem_config_slow_long, 375),
|
LONG_SLOW(ConfigProtos.Config.LoRaConfig.ModemPreset.LongSlow, R.string.modem_config_slow_long, 375),
|
||||||
VERY_LONG(ChannelProtos.ChannelSettings.ModemConfig.VLongSlow, R.string.modem_config_very_long, 375);
|
VERY_LONG(ConfigProtos.Config.LoRaConfig.ModemPreset.VLongSlow, R.string.modem_config_very_long, 375);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromConfig(modemConfig: ChannelProtos.ChannelSettings.ModemConfig?): ChannelOption? {
|
fun fromConfig(modemPreset: ConfigProtos.Config.LoRaConfig.ModemPreset?): ChannelOption? {
|
||||||
for (option in values()) {
|
for (option in values()) {
|
||||||
if (option.modemConfig == modemConfig)
|
if (option.modemPreset == modemPreset)
|
||||||
return option
|
return option
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ data class ChannelSet(
|
||||||
private fun urlToChannels(url: Uri): AppOnlyProtos.ChannelSet {
|
private fun urlToChannels(url: Uri): AppOnlyProtos.ChannelSet {
|
||||||
val urlStr = url.toString()
|
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 pathRegex = Regex("$prefix(.*)", RegexOption.IGNORE_CASE)
|
||||||
val (base64) = pathRegex.find(urlStr)?.destructured
|
val (base64) = pathRegex.find(urlStr)?.destructured
|
||||||
?: throw MalformedURLException("Not a meshtastic URL: ${urlStr.take(40)}")
|
?: 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
|
/// 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
|
/// @param upperCasePrefix - portions of the URL can be upper case to make for more efficient QR codes
|
||||||
fun getChannelUrl(upperCasePrefix: Boolean = false): Uri {
|
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 channelBytes = protobuf.toByteArray() ?: ByteArray(0) // if unset just use empty
|
||||||
val enc = Base64.encodeToString(channelBytes, base64Flags)
|
val enc = Base64.encodeToString(channelBytes, base64Flags)
|
||||||
|
|
||||||
val p = if (upperCasePrefix)
|
val p = if (upperCasePrefix)
|
||||||
prefix.toUpperCase()
|
prefix.uppercase()
|
||||||
else
|
else
|
||||||
prefix
|
prefix
|
||||||
return Uri.parse("$p$enc")
|
return Uri.parse("$p$enc")
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ fun getInitials(nameIn: String): String {
|
||||||
val words = name.split(Regex("\\s+")).filter { it.isNotEmpty() }
|
val words = name.split(Regex("\\s+")).filter { it.isNotEmpty() }
|
||||||
|
|
||||||
val initials = when (words.size) {
|
val initials = when (words.size) {
|
||||||
in 0..minchars - 1 -> {
|
in 0 until minchars -> {
|
||||||
val nm = if (name.length >= 1)
|
val nm = if (name.isNotEmpty())
|
||||||
name.first() + name.drop(1).filterNot { c -> c.lowercase() in "aeiou" }
|
name.first() + name.drop(1).filterNot { c -> c.lowercase() in "aeiou" }
|
||||||
else
|
else
|
||||||
""
|
""
|
||||||
|
|
@ -101,8 +101,8 @@ class UIViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// various radio settings (including the channel)
|
/// various radio settings (including the channel)
|
||||||
private val _radioConfig = MutableLiveData<RadioConfigProtos.RadioConfig?>()
|
private val _deviceConfig = MutableLiveData<ConfigProtos.Config?>()
|
||||||
val radioConfig: LiveData<RadioConfigProtos.RadioConfig?> get() = _radioConfig
|
val deviceConfig: LiveData<ConfigProtos.Config?> get() = _deviceConfig
|
||||||
|
|
||||||
private val _channels = MutableLiveData<ChannelSet?>()
|
private val _channels = MutableLiveData<ChannelSet?>()
|
||||||
val channels: LiveData<ChannelSet?> get() = _channels
|
val channels: LiveData<ChannelSet?> get() = _channels
|
||||||
|
|
@ -123,7 +123,7 @@ class UIViewModel @Inject constructor(
|
||||||
|
|
||||||
var positionBroadcastSecs: Int?
|
var positionBroadcastSecs: Int?
|
||||||
get() {
|
get() {
|
||||||
_radioConfig.value?.preferences?.let {
|
_deviceConfig.value?.position?.let {
|
||||||
if (it.positionBroadcastSecs > 0) return it.positionBroadcastSecs
|
if (it.positionBroadcastSecs > 0) return it.positionBroadcastSecs
|
||||||
// These default values are borrowed from the device code.
|
// These default values are borrowed from the device code.
|
||||||
return 15 * 60
|
return 15 * 60
|
||||||
|
|
@ -131,50 +131,50 @@ class UIViewModel @Inject constructor(
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
val config = _radioConfig.value
|
val config = _deviceConfig.value
|
||||||
if (value != null && config != null) {
|
if (value != null && config != null) {
|
||||||
val builder = config.toBuilder()
|
val builder = config.toBuilder()
|
||||||
builder.preferencesBuilder.positionBroadcastSecs = value
|
builder.positionBuilder.positionBroadcastSecs = value
|
||||||
setRadioConfig(builder.build())
|
setDeviceConfig(builder.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var lsSleepSecs: Int?
|
var lsSleepSecs: Int?
|
||||||
get() = _radioConfig.value?.preferences?.lsSecs
|
get() = _deviceConfig.value?.power?.lsSecs
|
||||||
set(value) {
|
set(value) {
|
||||||
val config = _radioConfig.value
|
val config = _deviceConfig.value
|
||||||
if (value != null && config != null) {
|
if (value != null && config != null) {
|
||||||
val builder = config.toBuilder()
|
val builder = config.toBuilder()
|
||||||
builder.preferencesBuilder.lsSecs = value
|
builder.powerBuilder.lsSecs = value
|
||||||
setRadioConfig(builder.build())
|
setDeviceConfig(builder.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var locationShareDisabled: Boolean
|
var gpsDisabled: Boolean
|
||||||
get() = _radioConfig.value?.preferences?.locationShareDisabled ?: false
|
get() = _deviceConfig.value?.position?.gpsDisabled ?: false
|
||||||
set(value) {
|
set(value) {
|
||||||
val config = _radioConfig.value
|
val config = _deviceConfig.value
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
val builder = config.toBuilder()
|
val builder = config.toBuilder()
|
||||||
builder.preferencesBuilder.locationShareDisabled = value
|
builder.positionBuilder.gpsDisabled = value
|
||||||
setRadioConfig(builder.build())
|
setDeviceConfig(builder.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isPowerSaving: Boolean?
|
var isPowerSaving: Boolean?
|
||||||
get() = _radioConfig.value?.preferences?.isPowerSaving
|
get() = _deviceConfig.value?.power?.isPowerSaving
|
||||||
set(value) {
|
set(value) {
|
||||||
val config = _radioConfig.value
|
val config = _deviceConfig.value
|
||||||
if (value != null && config != null) {
|
if (value != null && config != null) {
|
||||||
val builder = config.toBuilder()
|
val builder = config.toBuilder()
|
||||||
builder.preferencesBuilder.isPowerSaving = value
|
builder.powerBuilder.isPowerSaving = value
|
||||||
setRadioConfig(builder.build())
|
setDeviceConfig(builder.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var region: RadioConfigProtos.RegionCode
|
var region: ConfigProtos.Config.LoRaConfig.RegionCode
|
||||||
get() = meshService?.region?.let { RadioConfigProtos.RegionCode.forNumber(it) }
|
get() = meshService?.region?.let { ConfigProtos.Config.LoRaConfig.RegionCode.forNumber(it) }
|
||||||
?: RadioConfigProtos.RegionCode.Unset
|
?: ConfigProtos.Config.LoRaConfig.RegionCode.Unset
|
||||||
set(value) {
|
set(value) {
|
||||||
meshService?.region = value.number
|
meshService?.region = value.number
|
||||||
}
|
}
|
||||||
|
|
@ -216,10 +216,10 @@ class UIViewModel @Inject constructor(
|
||||||
val primaryChannel: Channel? get() = _channels.value?.primaryChannel
|
val primaryChannel: Channel? get() = _channels.value?.primaryChannel
|
||||||
|
|
||||||
// Set the radio config (also updates our saved copy in preferences)
|
// 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!")
|
debug("Setting new radio config!")
|
||||||
meshService?.radioConfig = c.toByteArray()
|
meshService?.deviceConfig = c.toByteArray()
|
||||||
_radioConfig.value =
|
_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)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,13 +60,13 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi
|
||||||
|
|
||||||
private fun handleAdminPacket(pr: MeshProtos.ToRadio, d: AdminProtos.AdminMessage) {
|
private fun handleAdminPacket(pr: MeshProtos.ToRadio, d: AdminProtos.AdminMessage) {
|
||||||
when {
|
when {
|
||||||
d.getRadioRequest ->
|
d.getConfigRequest == AdminProtos.AdminMessage.ConfigType.LORA_CONFIG ->
|
||||||
sendAdmin(pr.packet.to, pr.packet.from, pr.packet.id) {
|
sendAdmin(pr.packet.to, pr.packet.from, pr.packet.id) {
|
||||||
getRadioResponse = RadioConfigProtos.RadioConfig.newBuilder().apply {
|
getConfigResponse = ConfigProtos.Config.newBuilder().apply {
|
||||||
|
|
||||||
preferences =
|
lora =
|
||||||
RadioConfigProtos.RadioConfig.UserPreferences.newBuilder().apply {
|
ConfigProtos.Config.LoRaConfig.newBuilder().apply {
|
||||||
region = RadioConfigProtos.RegionCode.TW
|
region = ConfigProtos.Config.LoRaConfig.RegionCode.TW
|
||||||
// FIXME set critical times?
|
// FIXME set critical times?
|
||||||
}.build()
|
}.build()
|
||||||
}.build()
|
}.build()
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ class MeshService : Service(), Logging {
|
||||||
class NodeNumNotFoundException(id: Int) : NodeNotFoundException("NodeNum not found $id")
|
class NodeNumNotFoundException(id: Int) : NodeNotFoundException("NodeNum not found $id")
|
||||||
class IdNotFoundException(id: String) : NodeNotFoundException("ID 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)
|
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 */
|
/** 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
|
private var locationFlow: Job? = null
|
||||||
|
|
||||||
// If we've ever read a valid region code from our device it will be here
|
// 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 {
|
private fun getSenderName(packet: DataPacket?): String {
|
||||||
val name = nodeDBbyID[packet?.from]?.user?.longName
|
val name = nodeDBbyID[packet?.from]?.user?.longName
|
||||||
|
|
@ -350,7 +350,7 @@ class MeshService : Service(), Logging {
|
||||||
|
|
||||||
var myNodeInfo: MyNodeInfo? = null
|
var myNodeInfo: MyNodeInfo? = null
|
||||||
|
|
||||||
private var radioConfig: RadioConfigProtos.RadioConfig? = null
|
private var deviceConfig: ConfigProtos.Config? = null
|
||||||
|
|
||||||
private var channels = fixupChannelList(listOf())
|
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
|
// For the time being we only care about admin messages from our local node
|
||||||
if (fromNodeNum == myNodeNum) {
|
if (fromNodeNum == myNodeNum) {
|
||||||
when (a.variantCase) {
|
when (a.variantCase) {
|
||||||
AdminProtos.AdminMessage.VariantCase.GET_RADIO_RESPONSE -> {
|
AdminProtos.AdminMessage.VariantCase.GET_CONFIG_RESPONSE -> {
|
||||||
debug("Admin: received radioConfig")
|
debug("Admin: received deviceConfig")
|
||||||
radioConfig = a.getRadioResponse
|
deviceConfig = a.getConfigResponse
|
||||||
requestChannel(0) // Now start reading channels
|
requestChannel(0) // Now start reading channels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -983,7 +983,7 @@ class MeshService : Service(), Logging {
|
||||||
sleepTimeout = serviceScope.handledLaunch {
|
sleepTimeout = serviceScope.handledLaunch {
|
||||||
try {
|
try {
|
||||||
// If we have a valid timeout, wait that long (+30 seconds) otherwise, just wait 30 seconds
|
// 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")
|
debug("Waiting for sleeping device, timeout=$timeout secs")
|
||||||
delay(timeout * 1000L)
|
delay(timeout * 1000L)
|
||||||
|
|
@ -1075,7 +1075,7 @@ class MeshService : Service(), Logging {
|
||||||
|
|
||||||
private fun onRadioConnectionState(state: RadioServiceConnectionState) {
|
private fun onRadioConnectionState(state: RadioServiceConnectionState) {
|
||||||
// sleep now disabled by default on ESP32, permanent is true unless isPowerSaving enabled
|
// 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 connected = state.isConnected
|
||||||
val permanent = state.isPermanent || !lsEnabled
|
val permanent = state.isPermanent || !lsEnabled
|
||||||
onConnectionChanged(
|
onConnectionChanged(
|
||||||
|
|
@ -1105,7 +1105,7 @@ class MeshService : Service(), Logging {
|
||||||
|
|
||||||
MeshProtos.FromRadio.NODE_INFO_FIELD_NUMBER -> handleNodeInfo(proto.nodeInfo)
|
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")
|
else -> errormsg("Unexpected FromRadio variant")
|
||||||
}
|
}
|
||||||
|
|
@ -1249,7 +1249,7 @@ class MeshService : Service(), Logging {
|
||||||
regenMyNodeInfo()
|
regenMyNodeInfo()
|
||||||
|
|
||||||
// We'll need to get a new set of channels and settings now
|
// We'll need to get a new set of channels and settings now
|
||||||
radioConfig = null
|
deviceConfig = null
|
||||||
|
|
||||||
// prefill the channel array with null channels
|
// prefill the channel array with null channels
|
||||||
channels = fixupChannelList(listOf<ChannelProtos.Channel>())
|
channels = fixupChannelList(listOf<ChannelProtos.Channel>())
|
||||||
|
|
@ -1272,21 +1272,21 @@ class MeshService : Service(), Logging {
|
||||||
|
|
||||||
private fun setRegionOnDevice() {
|
private fun setRegionOnDevice() {
|
||||||
val curConfigRegion =
|
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) {
|
if (deviceVersion >= minFirmwareVersion) {
|
||||||
info("Telling device to upgrade region")
|
info("Telling device to upgrade region")
|
||||||
|
|
||||||
// Tell the device to set the new region field (old devices will simply ignore this)
|
// 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 newConfig = currentConfig.toBuilder()
|
||||||
|
|
||||||
val newPrefs = currentConfig.preferences.toBuilder()
|
val newPrefs = currentConfig.lora.toBuilder()
|
||||||
newPrefs.regionValue = curRegionValue
|
newPrefs.regionValue = curRegionValue
|
||||||
newConfig.preferences = newPrefs.build()
|
newConfig.lora = newPrefs.build()
|
||||||
|
|
||||||
sendRadioConfig(newConfig.build())
|
sendDeviceConfig(newConfig.build())
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
warn("Device is too old to understand region changes")
|
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
|
// Try to pull our region code from the new preferences field
|
||||||
// FIXME - do not check net - figuring out why board is rebooting
|
// FIXME - do not check net - figuring out why board is rebooting
|
||||||
val curConfigRegion =
|
val curConfigRegion =
|
||||||
radioConfig?.preferences?.region ?: RadioConfigProtos.RegionCode.Unset
|
deviceConfig?.lora?.region ?: ConfigProtos.Config.LoRaConfig.RegionCode.Unset
|
||||||
if (curConfigRegion != RadioConfigProtos.RegionCode.Unset) {
|
if (curConfigRegion != ConfigProtos.Config.LoRaConfig.RegionCode.Unset) {
|
||||||
info("Using device region $curConfigRegion (code ${curConfigRegion.number})")
|
info("Using device region $curConfigRegion (code ${curConfigRegion.number})")
|
||||||
curRegionValue = 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")
|
info("Device firmware is too old, faking config so firmware update can occur")
|
||||||
onHasSettings()
|
onHasSettings()
|
||||||
} else
|
} else
|
||||||
requestRadioConfig()
|
requestDeviceConfig()
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
warn("Ignoring stale config complete")
|
warn("Ignoring stale config complete")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestRadioConfig() {
|
private fun requestDeviceConfig() {
|
||||||
sendToRadio(newMeshPacketTo(myNodeNum).buildAdminPacket(wantResponse = true) {
|
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
|
/** 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
|
// send the packet into the mesh
|
||||||
sendToRadio(newMeshPacketTo(myNodeNum).buildAdminPacket {
|
sendToRadio(newMeshPacketTo(myNodeNum).buildAdminPacket {
|
||||||
setRadio = c
|
setConfig = c
|
||||||
})
|
})
|
||||||
|
|
||||||
// Update our cached copy
|
// Update our cached copy
|
||||||
this@MeshService.radioConfig = c
|
this@MeshService.deviceConfig = c
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set our radio config
|
/** Set our radio config
|
||||||
*/
|
*/
|
||||||
private fun setRadioConfig(payload: ByteArray) {
|
private fun setDeviceConfig(payload: ByteArray) {
|
||||||
val parsed = RadioConfigProtos.RadioConfig.parseFrom(payload)
|
val parsed = ConfigProtos.Config.parseFrom(payload)
|
||||||
|
|
||||||
sendRadioConfig(parsed)
|
sendDeviceConfig(parsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1690,13 +1690,13 @@ class MeshService : Service(), Logging {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRadioConfig(): ByteArray = toRemoteExceptions {
|
override fun getDeviceConfig(): ByteArray = toRemoteExceptions {
|
||||||
this@MeshService.radioConfig?.toByteArray()
|
this@MeshService.deviceConfig?.toByteArray()
|
||||||
?: throw NoRadioConfigException()
|
?: throw NoDeviceConfigException()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setRadioConfig(payload: ByteArray) = toRemoteExceptions {
|
override fun setDeviceConfig(payload: ByteArray) = toRemoteExceptions {
|
||||||
this@MeshService.setRadioConfig(payload)
|
this@MeshService.setDeviceConfig(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChannels(): ByteArray = toRemoteExceptions {
|
override fun getChannels(): ByteArray = toRemoteExceptions {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package com.geeksville.mesh.service
|
||||||
import com.geeksville.mesh.DataPacket
|
import com.geeksville.mesh.DataPacket
|
||||||
import com.geeksville.mesh.MyNodeInfo
|
import com.geeksville.mesh.MyNodeInfo
|
||||||
import com.geeksville.mesh.NodeInfo
|
import com.geeksville.mesh.NodeInfo
|
||||||
import com.geeksville.mesh.RadioConfigProtos
|
import com.geeksville.mesh.ConfigProtos
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
/// Our saved preferences as stored on disk
|
/// Our saved preferences as stored on disk
|
||||||
|
|
@ -12,7 +12,7 @@ data class MeshServiceSettingsData(
|
||||||
val nodeDB: Array<NodeInfo>,
|
val nodeDB: Array<NodeInfo>,
|
||||||
val myInfo: MyNodeInfo,
|
val myInfo: MyNodeInfo,
|
||||||
val messages: Array<DataPacket>,
|
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 {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
|
|
|
||||||
|
|
@ -37,18 +37,18 @@ class AdvancedSettingsFragment : ScreenFragment("Advanced Settings"), Logging {
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
model.radioConfig.observe(viewLifecycleOwner) {
|
model.deviceConfig.observe(viewLifecycleOwner) {
|
||||||
binding.positionBroadcastPeriodEditText.setText(model.positionBroadcastSecs.toString())
|
binding.positionBroadcastPeriodEditText.setText(model.positionBroadcastSecs.toString())
|
||||||
binding.lsSleepEditText.setText(model.lsSleepSecs.toString())
|
binding.lsSleepEditText.setText(model.lsSleepSecs.toString())
|
||||||
binding.positionBroadcastPeriodView.isEnabled = !model.locationShareDisabled
|
binding.positionBroadcastPeriodView.isEnabled = !model.gpsDisabled
|
||||||
binding.positionBroadcastSwitch.isChecked = !model.locationShareDisabled
|
binding.positionBroadcastSwitch.isChecked = !model.gpsDisabled
|
||||||
binding.lsSleepView.isEnabled = model.isPowerSaving ?: false
|
binding.lsSleepView.isEnabled = model.isPowerSaving ?: false
|
||||||
binding.lsSleepSwitch.isChecked = model.isPowerSaving ?: false
|
binding.lsSleepSwitch.isChecked = model.isPowerSaving ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
model.connectionState.observe(viewLifecycleOwner) { connectionState ->
|
model.connectionState.observe(viewLifecycleOwner) { connectionState ->
|
||||||
val connected = connectionState == MeshService.ConnectionState.CONNECTED
|
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.lsSleepView.isEnabled = connected && model.isPowerSaving ?: false
|
||||||
binding.positionBroadcastSwitch.isEnabled = connected
|
binding.positionBroadcastSwitch.isEnabled = connected
|
||||||
binding.lsSleepSwitch.isEnabled = connected
|
binding.lsSleepSwitch.isEnabled = connected
|
||||||
|
|
@ -58,7 +58,7 @@ class AdvancedSettingsFragment : ScreenFragment("Advanced Settings"), Logging {
|
||||||
val textEdit = binding.positionBroadcastPeriodEditText
|
val textEdit = binding.positionBroadcastPeriodEditText
|
||||||
val n = textEdit.text.toString().toIntOrNull()
|
val n = textEdit.text.toString().toIntOrNull()
|
||||||
val minBroadcastPeriodSecs =
|
val minBroadcastPeriodSecs =
|
||||||
ChannelOption.fromConfig(model.primaryChannel?.modemConfig)?.minBroadcastPeriodSecs
|
ChannelOption.fromConfig(model.deviceConfig.value?.lora?.modemPreset)?.minBroadcastPeriodSecs
|
||||||
?: ChannelOption.defaultMinBroadcastPeriod
|
?: ChannelOption.defaultMinBroadcastPeriod
|
||||||
|
|
||||||
if (n != null && n < MAX_INT_DEVICE && (n == 0 || n >= minBroadcastPeriodSecs)) {
|
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 ->
|
binding.positionBroadcastSwitch.setOnCheckedChangeListener { view, isChecked ->
|
||||||
if (view.isPressed) {
|
if (view.isPressed) {
|
||||||
model.locationShareDisabled = !isChecked
|
model.gpsDisabled = !isChecked
|
||||||
debug("User changed locationShare to $isChecked")
|
debug("User changed locationShare to $isChecked")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import com.geeksville.android.hideKeyboard
|
||||||
import com.geeksville.android.isGooglePlayAvailable
|
import com.geeksville.android.isGooglePlayAvailable
|
||||||
import com.geeksville.mesh.AppOnlyProtos
|
import com.geeksville.mesh.AppOnlyProtos
|
||||||
import com.geeksville.mesh.ChannelProtos
|
import com.geeksville.mesh.ChannelProtos
|
||||||
|
import com.geeksville.mesh.ConfigProtos
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
import com.geeksville.mesh.android.hasCameraPermission
|
import com.geeksville.mesh.android.hasCameraPermission
|
||||||
import com.geeksville.mesh.databinding.ChannelFragmentBinding
|
import com.geeksville.mesh.databinding.ChannelFragmentBinding
|
||||||
|
|
@ -107,15 +108,15 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
|
||||||
binding.channelNameEdit.setText(channel.humanName)
|
binding.channelNameEdit.setText(channel.humanName)
|
||||||
|
|
||||||
// For now, we only let the user edit/save channels while the radio is awake - because the service
|
// 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
|
binding.editableCheckbox.isEnabled = connected
|
||||||
|
|
||||||
val bitmap = channels.qrCode
|
val bitmap = channels.qrCode
|
||||||
if (bitmap != null)
|
if (bitmap != null)
|
||||||
binding.qrView.setImageBitmap(bitmap)
|
binding.qrView.setImageBitmap(bitmap)
|
||||||
|
|
||||||
val modemConfig = channel.modemConfig
|
val modemPreset = model.deviceConfig.value?.lora?.modemPreset
|
||||||
val channelOption = ChannelOption.fromConfig(modemConfig)
|
val channelOption = ChannelOption.fromConfig(modemPreset)
|
||||||
binding.filledExposedDropdown.setText(
|
binding.filledExposedDropdown.setText(
|
||||||
getString(
|
getString(
|
||||||
channelOption?.configRes ?: R.string.modem_config_unrecognized
|
channelOption?.configRes ?: R.string.modem_config_unrecognized
|
||||||
|
|
@ -128,12 +129,12 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
|
||||||
binding.editableCheckbox.isEnabled = false
|
binding.editableCheckbox.isEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
val modemConfigs = ChannelOption.values()
|
val modemPresets = ChannelOption.values()
|
||||||
val modemConfigList = modemConfigs.map { getString(it.configRes) }
|
val modemPresetList = modemPresets.map { getString(it.configRes) }
|
||||||
val adapter = ArrayAdapter(
|
val adapter = ArrayAdapter(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
R.layout.dropdown_menu_popup_item,
|
R.layout.dropdown_menu_popup_item,
|
||||||
modemConfigList
|
modemPresetList
|
||||||
)
|
)
|
||||||
|
|
||||||
binding.filledExposedDropdown.setAdapter(adapter)
|
binding.filledExposedDropdown.setAdapter(adapter)
|
||||||
|
|
@ -174,10 +175,10 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
|
||||||
private fun installSettings(newChannel: ChannelProtos.ChannelSettings) {
|
private fun installSettings(newChannel: ChannelProtos.ChannelSettings) {
|
||||||
val newSet =
|
val newSet =
|
||||||
ChannelSet(AppOnlyProtos.ChannelSet.newBuilder().addSettings(newChannel).build())
|
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 {
|
try {
|
||||||
model.setChannels(newSet)
|
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) {
|
} catch (ex: RemoteException) {
|
||||||
errormsg("ignoring channel problem", ex)
|
errormsg("ignoring channel problem", ex)
|
||||||
|
|
||||||
|
|
@ -282,7 +283,7 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
// User just unlocked for editing - remove the # goo around the channel name
|
// User just unlocked for editing - remove the # goo around the channel name
|
||||||
model.channels.value?.primaryChannel?.let { ch ->
|
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
|
originalName = ch.settings.name
|
||||||
binding.channelNameEdit.setText(originalName)
|
binding.channelNameEdit.setText(originalName)
|
||||||
}
|
}
|
||||||
|
|
@ -303,18 +304,20 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
|
||||||
// Find the new modem config
|
// Find the new modem config
|
||||||
val selectedChannelOptionString =
|
val selectedChannelOptionString =
|
||||||
binding.filledExposedDropdown.editableText.toString()
|
binding.filledExposedDropdown.editableText.toString()
|
||||||
var modemConfig = getModemConfig(selectedChannelOptionString)
|
var modemPreset = getModemPreset(selectedChannelOptionString)
|
||||||
if (modemConfig == ChannelProtos.ChannelSettings.ModemConfig.UNRECOGNIZED) // Huh? didn't find it - keep same
|
// if (modemPreset == ConfigProtos.Config.LoRaConfig.ModemPreset.UNRECOGNIZED) // Huh? didn't find it - keep same
|
||||||
modemConfig = oldPrimary.settings.modemConfig
|
// 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
|
// 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
|
// Install a new customized channel
|
||||||
debug("ASSIGNING NEW AES256 KEY")
|
debug("ASSIGNING NEW AES256 KEY")
|
||||||
val random = SecureRandom()
|
val random = SecureRandom()
|
||||||
val bytes = ByteArray(32)
|
val bytes = ByteArray(32)
|
||||||
random.nextBytes(bytes)
|
random.nextBytes(bytes)
|
||||||
newSettings.name = newName
|
newSettings.name = newName.take(11) // proto max_size:12
|
||||||
newSettings.psk = ByteString.copyFrom(bytes)
|
newSettings.psk = ByteString.copyFrom(bytes)
|
||||||
} else {
|
} else {
|
||||||
debug("Switching back to default channel")
|
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
|
// No matter what apply the speed selection from the user
|
||||||
newSettings.modemConfig = modemConfig
|
// newSettings.modemConfig = modemPreset -> TODO add from LoraConfig.ModemPreset?
|
||||||
|
|
||||||
installSettings(newSettings.build())
|
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()) {
|
for (item in ChannelOption.values()) {
|
||||||
if (getString(item.configRes) == selectedChannelOptionString)
|
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 =
|
private val requestPermissionAndScanLauncher =
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ class ContactsFragment : ScreenFragment("Messages"), Logging {
|
||||||
val nodes = model.nodeDB.nodes.value!!
|
val nodes = model.nodeDB.nodes.value!!
|
||||||
val node = nodes[if (isLocal) contact.to else contact.from]
|
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 channels = model.channels.value
|
||||||
val primaryChannel = channels?.primaryChannel
|
val primaryChannel = channels?.primaryChannel
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -296,9 +296,6 @@ class MessagesFragment : Fragment(), Logging {
|
||||||
val connected = connectionState == MeshService.ConnectionState.CONNECTED
|
val connected = connectionState == MeshService.ConnectionState.CONNECTED
|
||||||
binding.textInputLayout.isEnabled = connected
|
binding.textInputLayout.isEnabled = connected
|
||||||
binding.sendButton.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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import com.geeksville.android.hideKeyboard
|
||||||
import com.geeksville.android.isGooglePlayAvailable
|
import com.geeksville.android.isGooglePlayAvailable
|
||||||
import com.geeksville.mesh.MainActivity
|
import com.geeksville.mesh.MainActivity
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
import com.geeksville.mesh.RadioConfigProtos
|
import com.geeksville.mesh.ConfigProtos
|
||||||
import com.geeksville.mesh.android.*
|
import com.geeksville.mesh.android.*
|
||||||
import com.geeksville.mesh.databinding.SettingsFragmentBinding
|
import com.geeksville.mesh.databinding.SettingsFragmentBinding
|
||||||
import com.geeksville.mesh.model.BluetoothViewModel
|
import com.geeksville.mesh.model.BluetoothViewModel
|
||||||
|
|
@ -659,7 +659,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
// update the region selection from the device
|
// update the region selection from the device
|
||||||
val region = model.region
|
val region = model.region
|
||||||
val spinner = binding.regionSpinner
|
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
|
spinner.onItemSelectedListener = null
|
||||||
|
|
||||||
debug("current region is $region")
|
debug("current region is $region")
|
||||||
|
|
@ -673,7 +673,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
spinner.isEnabled = true
|
spinner.isEnabled = true
|
||||||
|
|
||||||
// If actively connected possibly let the user update firmware
|
// 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)
|
// Update the status string (highest priority messages first)
|
||||||
val info = model.myNodeInfo.value
|
val info = model.myNodeInfo.value
|
||||||
|
|
@ -683,7 +683,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
(permissionsWarning != null) ->
|
(permissionsWarning != null) ->
|
||||||
statusText.text = permissionsWarning
|
statusText.text = permissionsWarning
|
||||||
|
|
||||||
region == RadioConfigProtos.RegionCode.Unset ->
|
region == ConfigProtos.Config.LoRaConfig.RegionCode.Unset ->
|
||||||
statusText.text = getString(R.string.must_set_region)
|
statusText.text = getString(R.string.must_set_region)
|
||||||
|
|
||||||
connected == MeshService.ConnectionState.CONNECTED -> {
|
connected == MeshService.ConnectionState.CONNECTED -> {
|
||||||
|
|
@ -705,7 +705,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
id: Long
|
id: Long
|
||||||
) {
|
) {
|
||||||
val item = parent.getItemAtPosition(position) as String?
|
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()) {
|
exceptionToSnackbar(requireView()) {
|
||||||
model.region = asProto
|
model.region = asProto
|
||||||
}
|
}
|
||||||
|
|
@ -718,8 +718,8 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// the sorted list of region names like arrayOf("US", "CN", "EU488")
|
/// the sorted list of region names like arrayOf("US", "CN", "EU488")
|
||||||
private val regions = RadioConfigProtos.RegionCode.values().filter {
|
private val regions = ConfigProtos.Config.LoRaConfig.RegionCode.values().filter {
|
||||||
it != RadioConfigProtos.RegionCode.UNRECOGNIZED
|
it != ConfigProtos.Config.LoRaConfig.RegionCode.UNRECOGNIZED
|
||||||
}.map {
|
}.map {
|
||||||
it.name
|
it.name
|
||||||
}.sorted()
|
}.sorted()
|
||||||
|
|
@ -746,10 +746,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
updateDevicesButtons(scanModel.devices.value)
|
updateDevicesButtons(scanModel.devices.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
model.radioConfig.observe(viewLifecycleOwner) {
|
model.deviceConfig.observe(viewLifecycleOwner) {
|
||||||
binding.provideLocationCheckbox.isEnabled =
|
binding.provideLocationCheckbox.isEnabled =
|
||||||
isGooglePlayAvailable(requireContext()) && !model.locationShareDisabled
|
isGooglePlayAvailable(requireContext()) && !model.gpsDisabled
|
||||||
if (model.locationShareDisabled) {
|
if (model.gpsDisabled) {
|
||||||
model.provideLocation.value = false
|
model.provideLocation.value = false
|
||||||
binding.provideLocationCheckbox.isChecked = false
|
binding.provideLocationCheckbox.isChecked = false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginEnd="64dp"
|
android:layout_marginEnd="64dp"
|
||||||
android:hint="@string/channel_name"
|
android:hint="@string/channel_name"
|
||||||
|
app:counterEnabled="true"
|
||||||
|
app:counterMaxLength="11"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
@ -23,7 +25,6 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:digits="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890- "
|
android:digits="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890- "
|
||||||
android:imeOptions="actionDone"
|
android:imeOptions="actionDone"
|
||||||
android:maxLength="15"
|
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text="@string/unset" />
|
android:text="@string/unset" />
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue