mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: Add firmware update module for Nordic nRF devices (#3782)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
parent
3e4e9d5f29
commit
4b93065c7e
18 changed files with 1461 additions and 4 deletions
|
|
@ -133,6 +133,7 @@ fun SettingsScreen(
|
|||
val localConfig by settingsViewModel.localConfig.collectAsStateWithLifecycle()
|
||||
val ourNode by settingsViewModel.ourNodeInfo.collectAsStateWithLifecycle()
|
||||
val isConnected by settingsViewModel.isConnected.collectAsStateWithLifecycle(false)
|
||||
val isDfuCapable by settingsViewModel.isDfuCapable.collectAsStateWithLifecycle()
|
||||
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
var isWaiting by remember { mutableStateOf(false) }
|
||||
|
|
@ -244,6 +245,7 @@ fun SettingsScreen(
|
|||
state = state,
|
||||
isManaged = localConfig.security.isManaged,
|
||||
excludedModulesUnlocked = excludedModulesUnlocked,
|
||||
isDfuCapable = isDfuCapable,
|
||||
onPreserveFavoritesToggle = { viewModel.setPreserveFavorites(it) },
|
||||
onRouteClick = { route ->
|
||||
isWaiting = true
|
||||
|
|
|
|||
|
|
@ -26,14 +26,17 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.meshtastic.core.common.BuildConfigProvider
|
||||
import org.meshtastic.core.data.repository.DeviceHardwareRepository
|
||||
import org.meshtastic.core.data.repository.MeshLogRepository
|
||||
import org.meshtastic.core.data.repository.NodeRepository
|
||||
import org.meshtastic.core.data.repository.RadioConfigRepository
|
||||
|
|
@ -44,6 +47,7 @@ import org.meshtastic.core.database.model.Node
|
|||
import org.meshtastic.core.datastore.UiPreferencesDataSource
|
||||
import org.meshtastic.core.model.Position
|
||||
import org.meshtastic.core.model.util.positionToMeter
|
||||
import org.meshtastic.core.prefs.radio.RadioPrefs
|
||||
import org.meshtastic.core.prefs.ui.UiPrefs
|
||||
import org.meshtastic.core.service.IMeshService
|
||||
import org.meshtastic.core.service.ServiceRepository
|
||||
|
|
@ -74,6 +78,8 @@ constructor(
|
|||
private val uiPreferencesDataSource: UiPreferencesDataSource,
|
||||
private val buildConfigProvider: BuildConfigProvider,
|
||||
private val databaseManager: DatabaseManager,
|
||||
private val deviceHardwareRepository: DeviceHardwareRepository,
|
||||
private val radioPrefs: RadioPrefs,
|
||||
) : ViewModel() {
|
||||
val myNodeInfo: StateFlow<MyNodeEntity?> = nodeRepository.myNodeInfo
|
||||
|
||||
|
|
@ -109,6 +115,28 @@ constructor(
|
|||
val appVersionName
|
||||
get() = buildConfigProvider.versionName
|
||||
|
||||
val isDfuCapable: StateFlow<Boolean> =
|
||||
combine(ourNodeInfo, serviceRepository.connectionState) { node, connectionState -> Pair(node, connectionState) }
|
||||
.flatMapLatest { (node, connectionState) ->
|
||||
if (node == null || !connectionState.isConnected()) {
|
||||
flowOf(false)
|
||||
} else {
|
||||
// Check BLE address
|
||||
val address = radioPrefs.devAddr
|
||||
if (address == null || !address.startsWith("x")) {
|
||||
flowOf(false)
|
||||
} else {
|
||||
// Check hardware
|
||||
val hwModel = node.user.hwModel.number
|
||||
flow {
|
||||
val hw = deviceHardwareRepository.getDeviceHardwareByModel(hwModel).getOrNull()
|
||||
emit(hw?.requiresDfu == true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.stateInWhileSubscribed(initialValue = false)
|
||||
|
||||
// Device DB cache limit (bounded by DatabaseConstants)
|
||||
val dbCacheLimit: StateFlow<Int> = databaseManager.cacheLimit
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import androidx.compose.material.icons.rounded.PowerSettingsNew
|
|||
import androidx.compose.material.icons.rounded.RestartAlt
|
||||
import androidx.compose.material.icons.rounded.Restore
|
||||
import androidx.compose.material.icons.rounded.Storage
|
||||
import androidx.compose.material.icons.rounded.SystemUpdate
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Switch
|
||||
|
|
@ -48,6 +49,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.navigation.FirmwareRoutes
|
||||
import org.meshtastic.core.navigation.Route
|
||||
import org.meshtastic.core.navigation.SettingsRoutes
|
||||
import org.meshtastic.core.strings.Res
|
||||
|
|
@ -59,6 +61,7 @@ import org.meshtastic.core.strings.debug_panel
|
|||
import org.meshtastic.core.strings.device_configuration
|
||||
import org.meshtastic.core.strings.export_configuration
|
||||
import org.meshtastic.core.strings.factory_reset
|
||||
import org.meshtastic.core.strings.firmware_update_title
|
||||
import org.meshtastic.core.strings.import_configuration
|
||||
import org.meshtastic.core.strings.message_device_managed
|
||||
import org.meshtastic.core.strings.module_settings
|
||||
|
|
@ -82,6 +85,7 @@ fun RadioConfigItemList(
|
|||
state: RadioConfigState,
|
||||
isManaged: Boolean,
|
||||
excludedModulesUnlocked: Boolean = false,
|
||||
isDfuCapable: Boolean = false,
|
||||
onPreserveFavoritesToggle: (Boolean) -> Unit = {},
|
||||
onRouteClick: (Enum<*>) -> Unit = {},
|
||||
onImport: () -> Unit = {},
|
||||
|
|
@ -194,6 +198,15 @@ fun RadioConfigItemList(
|
|||
ManagedMessage()
|
||||
}
|
||||
|
||||
if (isDfuCapable && state.isLocal) {
|
||||
ListItem(
|
||||
text = stringResource(Res.string.firmware_update_title),
|
||||
leadingIcon = Icons.Rounded.SystemUpdate,
|
||||
enabled = enabled,
|
||||
onClick = { onNavigate(FirmwareRoutes.FirmwareUpdate) },
|
||||
)
|
||||
}
|
||||
|
||||
ListItem(
|
||||
text = stringResource(Res.string.clean_node_database_title),
|
||||
leadingIcon = Icons.Rounded.CleaningServices,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue