mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor: updates for 2.2 release
reference https://github.com/meshtastic/protobufs/pull/368
This commit is contained in:
parent
0a47b8df3e
commit
e9ae0c66d9
5 changed files with 150 additions and 62 deletions
|
|
@ -178,9 +178,6 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi
|
|||
MeshProtos.FromRadio.newBuilder().apply {
|
||||
myInfo = MeshProtos.MyNodeInfo.newBuilder().apply {
|
||||
myNodeNum = MY_NODE
|
||||
messageTimeoutMsec = 5 * 60 * 1000
|
||||
firmwareVersion = "1.3.8" // Pretend to be running an older 1.3 version
|
||||
maxChannels = 8
|
||||
}.build()
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -123,9 +123,10 @@ class MeshService : Service(), Logging {
|
|||
"com.geeksville.mesh.service.MeshService"
|
||||
)
|
||||
|
||||
/** The minimmum firmware version we know how to talk to. We'll still be able to talk to 1.0 firmwares but only well enough to ask them to firmware update
|
||||
/** The minimum firmware version we know how to talk to. We'll still be able
|
||||
* to talk to 2.0 firmwares but only well enough to ask them to firmware update.
|
||||
*/
|
||||
val minDeviceVersion = DeviceVersion("1.3.43")
|
||||
val minDeviceVersion = DeviceVersion("2.0.21")
|
||||
}
|
||||
|
||||
enum class ConnectionState {
|
||||
|
|
@ -1156,6 +1157,7 @@ class MeshService : Service(), Logging {
|
|||
MeshProtos.FromRadio.CONFIG_FIELD_NUMBER -> handleDeviceConfig(proto.config)
|
||||
MeshProtos.FromRadio.MODULECONFIG_FIELD_NUMBER -> handleModuleConfig(proto.moduleConfig)
|
||||
MeshProtos.FromRadio.QUEUESTATUS_FIELD_NUMBER -> handleQueueStatus(proto.queueStatus)
|
||||
MeshProtos.FromRadio.METADATA_FIELD_NUMBER -> handleMetadata(proto.metadata)
|
||||
else -> errormsg("Unexpected FromRadio variant")
|
||||
}
|
||||
} catch (ex: InvalidProtocolBufferException) {
|
||||
|
|
@ -1265,6 +1267,7 @@ class MeshService : Service(), Logging {
|
|||
|
||||
|
||||
private var rawMyNodeInfo: MeshProtos.MyNodeInfo? = null
|
||||
private var rawDeviceMetadata: MeshProtos.DeviceMetadata? = null
|
||||
|
||||
/** Regenerate the myNodeInfo model. We call this twice. Once after we receive myNodeInfo from the device
|
||||
* and again after we have the node DB (which might allow us a better notion of our HwModel.
|
||||
|
|
@ -1274,6 +1277,7 @@ class MeshService : Service(), Logging {
|
|||
if (myInfo != null) {
|
||||
val a = radioInterfaceService.getBondedDeviceAddress()
|
||||
val isBluetoothInterface = a != null && a.startsWith("x")
|
||||
val firmwareVersion = rawDeviceMetadata?.firmwareVersion.orEmpty()
|
||||
|
||||
val nodeNum =
|
||||
myInfo.myNodeNum // Note: can't use the normal property because myNodeInfo not yet setup
|
||||
|
|
@ -1283,7 +1287,7 @@ class MeshService : Service(), Logging {
|
|||
val mi = with(myInfo) {
|
||||
MyNodeInfo(
|
||||
myNodeNum,
|
||||
hasGps,
|
||||
false,
|
||||
hwModelStr,
|
||||
firmwareVersion,
|
||||
firmwareUpdateFilename?.appLoad != null && firmwareUpdateFilename?.littlefs != null,
|
||||
|
|
@ -1292,12 +1296,12 @@ class MeshService : Service(), Logging {
|
|||
DeviceVersion(firmwareVersion)
|
||||
),
|
||||
currentPacketId and 0xffffffffL,
|
||||
if (messageTimeoutMsec == 0) 5 * 60 * 1000 else messageTimeoutMsec, // constants from current device code
|
||||
5 * 60 * 1000, // constants from current device code
|
||||
minAppVersion,
|
||||
maxChannels,
|
||||
hasWifi,
|
||||
channelUtilization,
|
||||
airUtilTx
|
||||
8,
|
||||
false,
|
||||
0f,
|
||||
0f,
|
||||
)
|
||||
}
|
||||
newMyNodeInfo = mi
|
||||
|
|
@ -1311,27 +1315,13 @@ class MeshService : Service(), Logging {
|
|||
/// Track types of devices and firmware versions in use
|
||||
GeeksvilleApplication.analytics.setUserInfo(
|
||||
DataPair("firmware", mi.firmwareVersion),
|
||||
DataPair("has_gps", mi.hasGPS),
|
||||
DataPair("hw_model", mi.model),
|
||||
DataPair("dev_error_count", myInfo.errorCount)
|
||||
)
|
||||
|
||||
if (myInfo.errorCode != MeshProtos.CriticalErrorCode.UNSPECIFIED && myInfo.errorCode != MeshProtos.CriticalErrorCode.NONE) {
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"dev_error",
|
||||
DataPair("code", myInfo.errorCode.number),
|
||||
DataPair("address", myInfo.errorAddress),
|
||||
|
||||
// We also include this info, because it is required to correctly decode address from the map file
|
||||
DataPair("firmware", mi.firmwareVersion),
|
||||
DataPair("hw_model", mi.model)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the nodeinfo (called from either new API version or the old one)
|
||||
* Update MyNodeInfo (called from either new API version or the old one)
|
||||
*/
|
||||
private fun handleMyInfo(myInfo: MeshProtos.MyNodeInfo) {
|
||||
val packetToSave = MeshLog(
|
||||
|
|
@ -1353,6 +1343,21 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update our DeviceMetadata
|
||||
*/
|
||||
private fun handleMetadata(metadata: MeshProtos.DeviceMetadata) {
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"DeviceMetadata",
|
||||
System.currentTimeMillis(),
|
||||
metadata.toString()
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
rawDeviceMetadata = metadata
|
||||
}
|
||||
|
||||
/// If we've received our initial config, our radio settings and all of our channels, send any queued packets and broadcast connected to clients
|
||||
private fun onHasSettings() {
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ import com.geeksville.mesh.ui.components.config.EditDeviceProfileDialog
|
|||
import com.geeksville.mesh.ui.components.config.ExternalNotificationConfigItemList
|
||||
import com.geeksville.mesh.ui.components.config.LoRaConfigItemList
|
||||
import com.geeksville.mesh.ui.components.config.MQTTConfigItemList
|
||||
import com.geeksville.mesh.ui.components.config.NeighborInfoConfigItemList
|
||||
import com.geeksville.mesh.ui.components.config.NetworkConfigItemList
|
||||
import com.geeksville.mesh.ui.components.config.PacketResponseStateDialog
|
||||
import com.geeksville.mesh.ui.components.config.PositionConfigItemList
|
||||
|
|
@ -121,26 +122,27 @@ class DeviceSettingsFragment(val node: NodeInfo) : ScreenFragment("Radio Configu
|
|||
}
|
||||
}
|
||||
|
||||
enum class ConfigDest(val title: String, val route: String, val config: ConfigType) {
|
||||
DEVICE("Device", "device", ConfigType.DEVICE_CONFIG),
|
||||
POSITION("Position", "position", ConfigType.POSITION_CONFIG),
|
||||
POWER("Power", "power", ConfigType.POWER_CONFIG),
|
||||
NETWORK("Network", "network", ConfigType.NETWORK_CONFIG),
|
||||
DISPLAY("Display", "display", ConfigType.DISPLAY_CONFIG),
|
||||
LORA("LoRa", "lora", ConfigType.LORA_CONFIG),
|
||||
BLUETOOTH("Bluetooth", "bluetooth", ConfigType.BLUETOOTH_CONFIG);
|
||||
enum class ConfigDest(val title: String, val route: String) {
|
||||
DEVICE("Device", "device"),
|
||||
POSITION("Position", "position"),
|
||||
POWER("Power", "power"),
|
||||
NETWORK("Network", "network"),
|
||||
DISPLAY("Display", "display"),
|
||||
LORA("LoRa", "lora"),
|
||||
BLUETOOTH("Bluetooth", "bluetooth");
|
||||
}
|
||||
|
||||
enum class ModuleDest(val title: String, val route: String, val config: ModuleConfigType) {
|
||||
MQTT("MQTT", "mqtt", ModuleConfigType.MQTT_CONFIG),
|
||||
SERIAL("Serial", "serial", ModuleConfigType.SERIAL_CONFIG),
|
||||
EXTERNAL_NOTIFICATION("External Notification", "ext_not", ModuleConfigType.EXTNOTIF_CONFIG),
|
||||
STORE_FORWARD("Store & Forward", "store_forward", ModuleConfigType.STOREFORWARD_CONFIG),
|
||||
RANGE_TEST("Range Test", "range_test", ModuleConfigType.RANGETEST_CONFIG),
|
||||
TELEMETRY("Telemetry", "telemetry", ModuleConfigType.TELEMETRY_CONFIG),
|
||||
CANNED_MESSAGE("Canned Message", "canned_message", ModuleConfigType.CANNEDMSG_CONFIG),
|
||||
AUDIO("Audio", "audio", ModuleConfigType.AUDIO_CONFIG),
|
||||
REMOTE_HARDWARE("Remote Hardware", "remote_hardware", ModuleConfigType.REMOTEHARDWARE_CONFIG);
|
||||
enum class ModuleDest(val title: String, val route: String) {
|
||||
MQTT("MQTT", "mqtt"),
|
||||
SERIAL("Serial", "serial"),
|
||||
EXTERNAL_NOTIFICATION("External Notification", "ext_not"),
|
||||
STORE_FORWARD("Store & Forward", "store_forward"),
|
||||
RANGE_TEST("Range Test", "range_test"),
|
||||
TELEMETRY("Telemetry", "telemetry"),
|
||||
CANNED_MESSAGE("Canned Message", "canned_message"),
|
||||
AUDIO("Audio", "audio"),
|
||||
REMOTE_HARDWARE("Remote Hardware", "remote_hardware"),
|
||||
NEIGHBOR_INFO("Neighbor Info", "neighbor_info");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -375,19 +377,19 @@ fun RadioConfigNavHost(node: NodeInfo, viewModel: UIViewModel = viewModel()) {
|
|||
channelList.clear()
|
||||
viewModel.getChannel(destNum, 0)
|
||||
}
|
||||
is ConfigType -> {
|
||||
viewModel.getConfig(destNum, configType.number)
|
||||
is ConfigDest -> {
|
||||
viewModel.getConfig(destNum, configType.ordinal)
|
||||
}
|
||||
ModuleConfigType.CANNEDMSG_CONFIG -> {
|
||||
ModuleDest.CANNED_MESSAGE -> {
|
||||
(packetResponseState as PacketResponseState.Loading).total = 2
|
||||
viewModel.getCannedMessages(destNum)
|
||||
}
|
||||
ModuleConfigType.EXTNOTIF_CONFIG -> {
|
||||
ModuleDest.EXTERNAL_NOTIFICATION -> {
|
||||
(packetResponseState as PacketResponseState.Loading).total = 2
|
||||
viewModel.getRingtone(destNum)
|
||||
}
|
||||
is ModuleConfigType -> {
|
||||
viewModel.getModuleConfig(destNum, configType.number)
|
||||
is ModuleDest -> {
|
||||
viewModel.getModuleConfig(destNum, configType.ordinal)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -651,6 +653,19 @@ fun RadioConfigNavHost(node: NodeInfo, viewModel: UIViewModel = viewModel()) {
|
|||
}
|
||||
)
|
||||
}
|
||||
composable("neighbor_info") {
|
||||
NeighborInfoConfigItemList(
|
||||
neighborInfoConfig = moduleConfig.neighborInfo,
|
||||
enabled = connected,
|
||||
focusManager = focusManager,
|
||||
onSaveClicked = { neighborInfoInput ->
|
||||
focusManager.clearFocus()
|
||||
val config = moduleConfig { neighborInfo = neighborInfoInput }
|
||||
viewModel.setModuleConfig(destNum, config)
|
||||
moduleConfig = config
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -769,13 +784,13 @@ fun RadioSettingsScreen(
|
|||
item { PreferenceCategory(stringResource(R.string.device_settings)) }
|
||||
item { NavCard("User", enabled = enabled) { onRouteClick("USER") } }
|
||||
item { NavCard("Channels", enabled = enabled) { onRouteClick("CHANNELS") } }
|
||||
items(ConfigDest.values()) { configs ->
|
||||
NavCard(configs.title, enabled = enabled) { onRouteClick(configs.config) }
|
||||
items(ConfigDest.values()) { config ->
|
||||
NavCard(config.title, enabled = enabled) { onRouteClick(config) }
|
||||
}
|
||||
|
||||
item { PreferenceCategory(stringResource(R.string.module_settings)) }
|
||||
items(ModuleDest.values()) { modules ->
|
||||
NavCard(modules.title, enabled = enabled) { onRouteClick(modules.config) }
|
||||
items(ModuleDest.values()) { module ->
|
||||
NavCard(module.title, enabled = enabled) { onRouteClick(module) }
|
||||
}
|
||||
|
||||
if (isLocal) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
package com.geeksville.mesh.ui.components.config
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusManager
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.geeksville.mesh.ModuleConfigProtos
|
||||
import com.geeksville.mesh.copy
|
||||
import com.geeksville.mesh.ui.components.EditTextPreference
|
||||
import com.geeksville.mesh.ui.components.PreferenceCategory
|
||||
import com.geeksville.mesh.ui.components.PreferenceFooter
|
||||
import com.geeksville.mesh.ui.components.SwitchPreference
|
||||
|
||||
@Composable
|
||||
fun NeighborInfoConfigItemList(
|
||||
neighborInfoConfig: ModuleConfigProtos.ModuleConfig.NeighborInfoConfig,
|
||||
enabled: Boolean,
|
||||
focusManager: FocusManager,
|
||||
onSaveClicked: (ModuleConfigProtos.ModuleConfig.NeighborInfoConfig) -> Unit,
|
||||
) {
|
||||
var neighborInfoInput by remember(neighborInfoConfig) { mutableStateOf(neighborInfoConfig) }
|
||||
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
item { PreferenceCategory(text = "Neighbor Info Config") }
|
||||
|
||||
item {
|
||||
SwitchPreference(title = "Neighbor Info enabled",
|
||||
checked = neighborInfoInput.enabled,
|
||||
enabled = enabled,
|
||||
onCheckedChange = {
|
||||
neighborInfoInput = neighborInfoInput.copy { this.enabled = it }
|
||||
})
|
||||
}
|
||||
item { Divider() }
|
||||
|
||||
item {
|
||||
EditTextPreference(title = "Update interval (seconds)",
|
||||
value = neighborInfoInput.updateInterval,
|
||||
enabled = enabled,
|
||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onValueChanged = {
|
||||
neighborInfoInput = neighborInfoInput.copy { updateInterval = it }
|
||||
})
|
||||
}
|
||||
|
||||
item {
|
||||
PreferenceFooter(
|
||||
enabled = neighborInfoInput != neighborInfoConfig,
|
||||
onCancelClicked = {
|
||||
focusManager.clearFocus()
|
||||
neighborInfoInput = neighborInfoConfig
|
||||
},
|
||||
onSaveClicked = { onSaveClicked(neighborInfoInput) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun NeighborInfoConfigPreview(){
|
||||
NeighborInfoConfigItemList(
|
||||
neighborInfoConfig = ModuleConfigProtos.ModuleConfig.NeighborInfoConfig.getDefaultInstance(),
|
||||
enabled = true,
|
||||
focusManager = LocalFocusManager.current,
|
||||
onSaveClicked = { },
|
||||
)
|
||||
}
|
||||
|
|
@ -68,14 +68,6 @@ fun PowerConfigItemList(
|
|||
onValueChanged = { powerInput = powerInput.copy { waitBluetoothSecs = it } })
|
||||
}
|
||||
|
||||
item {
|
||||
EditTextPreference(title = "Mesh SDS timeout (seconds)",
|
||||
value = powerInput.meshSdsTimeoutSecs,
|
||||
enabled = enabled,
|
||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onValueChanged = { powerInput = powerInput.copy { meshSdsTimeoutSecs = it } })
|
||||
}
|
||||
|
||||
item {
|
||||
EditTextPreference(title = "Super deep sleep duration (seconds)",
|
||||
value = powerInput.sdsSecs,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue