mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat(db): introduce transactional config installation (#3209)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
parent
01290278e9
commit
6c0b2c55a0
4 changed files with 34 additions and 63 deletions
|
|
@ -118,16 +118,8 @@ constructor(
|
|||
|
||||
suspend fun upsert(node: NodeEntity) = withContext(dispatchers.io) { nodeInfoDao.upsert(node) }
|
||||
|
||||
suspend fun installMyNodeInfo(mi: MyNodeEntity) = withContext(dispatchers.io) {
|
||||
nodeInfoDao.clearMyNodeInfo()
|
||||
nodeInfoDao.setMyNodeInfo(mi)
|
||||
nodeInfoDao.clearNodeInfo()
|
||||
}
|
||||
|
||||
suspend fun installNodeDb(nodes: List<NodeEntity>) = withContext(dispatchers.io) {
|
||||
nodeInfoDao.clearNodeInfo()
|
||||
nodeInfoDao.putAll(nodes)
|
||||
}
|
||||
suspend fun installConfig(mi: MyNodeEntity, nodes: List<NodeEntity>) =
|
||||
withContext(dispatchers.io) { nodeInfoDao.installConfig(mi, nodes) }
|
||||
|
||||
suspend fun clearNodeDB() = withContext(dispatchers.io) { nodeInfoDao.clearNodeInfo() }
|
||||
|
||||
|
|
|
|||
|
|
@ -77,9 +77,6 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
|
|
@ -217,7 +214,6 @@ class MeshService :
|
|||
val absoluteMinDeviceVersion = DeviceVersion(BuildConfig.ABS_MIN_FW_VERSION)
|
||||
|
||||
private var configNonce = 1
|
||||
private const val CONFIG_WAIT_MS = 250L
|
||||
}
|
||||
|
||||
private var previousSummary: String? = null
|
||||
|
|
@ -323,9 +319,6 @@ class MeshService :
|
|||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
_lastAddress.value = meshPrefs.deviceAddress ?: NO_DEVICE_SELECTED
|
||||
|
||||
info("Creating mesh service")
|
||||
serviceNotifications.initChannels()
|
||||
// Switch to the IO thread
|
||||
|
|
@ -1406,6 +1399,7 @@ class MeshService :
|
|||
} else {
|
||||
ConnectionState.DISCONNECTED
|
||||
}
|
||||
|
||||
ConnectionState.DISCONNECTED -> ConnectionState.DISCONNECTED
|
||||
}
|
||||
onConnectionChanged(effectiveState)
|
||||
|
|
@ -1415,31 +1409,41 @@ class MeshService :
|
|||
PayloadVariantCase.entries.associateWith { variant: PayloadVariantCase ->
|
||||
when (variant) {
|
||||
PayloadVariantCase.PACKET -> { proto: MeshProtos.FromRadio -> handleReceivedMeshPacket(proto.packet) }
|
||||
|
||||
PayloadVariantCase.CONFIG_COMPLETE_ID -> { proto: MeshProtos.FromRadio ->
|
||||
handleConfigComplete(proto.configCompleteId)
|
||||
}
|
||||
|
||||
PayloadVariantCase.MY_INFO -> { proto: MeshProtos.FromRadio -> handleMyInfo(proto.myInfo) }
|
||||
PayloadVariantCase.NODE_INFO -> { proto: MeshProtos.FromRadio -> handleNodeInfo(proto.nodeInfo) }
|
||||
|
||||
PayloadVariantCase.CHANNEL -> { proto: MeshProtos.FromRadio -> handleChannel(proto.channel) }
|
||||
PayloadVariantCase.CONFIG -> { proto: MeshProtos.FromRadio -> handleDeviceConfig(proto.config) }
|
||||
|
||||
PayloadVariantCase.MODULECONFIG -> { proto: MeshProtos.FromRadio ->
|
||||
handleModuleConfig(proto.moduleConfig)
|
||||
}
|
||||
|
||||
PayloadVariantCase.QUEUESTATUS -> { proto: MeshProtos.FromRadio ->
|
||||
packetHandler.handleQueueStatus((proto.queueStatus))
|
||||
}
|
||||
|
||||
PayloadVariantCase.METADATA -> { proto: MeshProtos.FromRadio -> handleMetadata(proto.metadata) }
|
||||
PayloadVariantCase.MQTTCLIENTPROXYMESSAGE -> { proto: MeshProtos.FromRadio ->
|
||||
handleMqttProxyMessage(proto.mqttClientProxyMessage)
|
||||
}
|
||||
|
||||
PayloadVariantCase.DEVICEUICONFIG -> { proto: MeshProtos.FromRadio ->
|
||||
handleDeviceUiConfig(proto.deviceuiConfig)
|
||||
}
|
||||
|
||||
PayloadVariantCase.FILEINFO -> { proto: MeshProtos.FromRadio -> handleFileInfo(proto.fileInfo) }
|
||||
PayloadVariantCase.CLIENTNOTIFICATION -> { proto: MeshProtos.FromRadio ->
|
||||
handleClientNotification(proto.clientNotification)
|
||||
}
|
||||
|
||||
PayloadVariantCase.LOG_RECORD -> { proto: MeshProtos.FromRadio -> handleLogReord(proto.logRecord) }
|
||||
|
||||
PayloadVariantCase.REBOOTED -> { proto: MeshProtos.FromRadio -> handleRebooted(proto.rebooted) }
|
||||
PayloadVariantCase.XMODEMPACKET -> { proto: MeshProtos.FromRadio ->
|
||||
handleXmodemPacket(proto.xmodemPacket)
|
||||
|
|
@ -1818,25 +1822,15 @@ class MeshService :
|
|||
} else {
|
||||
myNodeInfo = newMyNodeInfo
|
||||
}
|
||||
serviceScope.handledLaunch {
|
||||
delay(CONFIG_WAIT_MS)
|
||||
radioInterfaceService.keepAlive()
|
||||
delay(CONFIG_WAIT_MS)
|
||||
}
|
||||
// This was our config request
|
||||
if (newNodes.isEmpty()) {
|
||||
errormsg("Did not receive a valid node info")
|
||||
} else {
|
||||
newNodes.forEach(::installNodeInfo)
|
||||
newNodes.clear() // Just to save RAM ;-)
|
||||
|
||||
serviceScope.handledLaunch {
|
||||
nodeRepository.installMyNodeInfo(myNodeInfo!!)
|
||||
nodeRepository.installNodeDb(nodeDBbyNodeNum.values.toList())
|
||||
}
|
||||
newNodes.clear()
|
||||
serviceScope.handledLaunch { nodeRepository.installConfig(myNodeInfo!!, nodeDBbyNodeNum.values.toList()) }
|
||||
|
||||
haveNodeDB = true // we now have nodes from real hardware
|
||||
|
||||
sendAnalytics()
|
||||
onHasSettings()
|
||||
onNodeDBChanged()
|
||||
|
|
@ -2004,10 +1998,6 @@ class MeshService :
|
|||
rememberReaction(packet.copy { from = myNodeNum })
|
||||
}
|
||||
|
||||
private val _lastAddress: MutableStateFlow<String?> = MutableStateFlow(null)
|
||||
val lastAddress: StateFlow<String?>
|
||||
get() = _lastAddress.asStateFlow()
|
||||
|
||||
fun clearDatabases() = serviceScope.handledLaunch {
|
||||
debug("Clearing nodeDB")
|
||||
nodeRepository.clearNodeDB()
|
||||
|
|
@ -2015,28 +2005,14 @@ class MeshService :
|
|||
|
||||
private fun updateLastAddress(deviceAddr: String?) {
|
||||
debug("setDeviceAddress: Passing through device change to radio service: ${deviceAddr.anonymize}")
|
||||
when (deviceAddr) {
|
||||
null,
|
||||
"",
|
||||
-> {
|
||||
debug("SetDeviceAddress: No previous device address, setting new one")
|
||||
_lastAddress.value = deviceAddr
|
||||
meshPrefs.deviceAddress = deviceAddr
|
||||
}
|
||||
|
||||
lastAddress.value,
|
||||
NO_DEVICE_SELECTED,
|
||||
-> {
|
||||
debug("SetDeviceAddress: Device address is the none or same, ignoring")
|
||||
}
|
||||
|
||||
else -> {
|
||||
debug("SetDeviceAddress: Device address changed from $lastAddress to $deviceAddr")
|
||||
_lastAddress.value = deviceAddr
|
||||
meshPrefs.deviceAddress = deviceAddr
|
||||
clearDatabases()
|
||||
clearNotifications()
|
||||
}
|
||||
if (deviceAddr == meshPrefs.deviceAddress || deviceAddr == NO_DEVICE_SELECTED) {
|
||||
debug("SetDeviceAddress: Device address is the none or same, ignoring")
|
||||
return
|
||||
} else {
|
||||
debug("SetDeviceAddress: Device address changed from ${meshPrefs.deviceAddress} to $deviceAddr")
|
||||
meshPrefs.deviceAddress = deviceAddr
|
||||
clearDatabases()
|
||||
clearNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2050,13 +2026,7 @@ class MeshService :
|
|||
override fun setDeviceAddress(deviceAddr: String?) = toRemoteExceptions {
|
||||
debug("Passing through device change to radio service: ${deviceAddr.anonymize}")
|
||||
updateLastAddress(deviceAddr)
|
||||
val res = radioInterfaceService.setDeviceAddress(deviceAddr)
|
||||
if (res) {
|
||||
discardNodeDB()
|
||||
} else {
|
||||
serviceBroadcasts.broadcastConnection()
|
||||
}
|
||||
res
|
||||
radioInterfaceService.setDeviceAddress(deviceAddr)
|
||||
}
|
||||
|
||||
// Note: bound methods don't get properly exception caught/logged, so do that with a
|
||||
|
|
|
|||
|
|
@ -221,4 +221,11 @@ interface NodeInfoDao {
|
|||
|
||||
@Query("UPDATE nodes SET notes = :notes WHERE num = :num")
|
||||
fun setNodeNotes(num: Int, notes: String)
|
||||
|
||||
@Transaction
|
||||
fun installConfig(mi: MyNodeEntity, nodes: List<NodeEntity>) {
|
||||
clearMyNodeInfo()
|
||||
setMyNodeInfo(mi)
|
||||
putAll(nodes.map { getVerifiedNodeForUpsert(it) })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ interface MeshPrefs {
|
|||
|
||||
@Singleton
|
||||
class MeshPrefsImpl @Inject constructor(@MeshSharedPreferences private val prefs: SharedPreferences) : MeshPrefs {
|
||||
override var deviceAddress: String? by NullableStringPrefDelegate(prefs, "device_address", null)
|
||||
override var deviceAddress: String? by NullableStringPrefDelegate(prefs, "device_address", NO_DEVICE_SELECTED)
|
||||
|
||||
override fun shouldProvideNodeLocation(nodeNum: Int?): Boolean =
|
||||
prefs.getBoolean(provideLocationKey(nodeNum), false)
|
||||
|
|
@ -45,3 +45,5 @@ class MeshPrefsImpl @Inject constructor(@MeshSharedPreferences private val prefs
|
|||
|
||||
private fun provideLocationKey(nodeNum: Int?) = "provide-location-$nodeNum"
|
||||
}
|
||||
|
||||
private const val NO_DEVICE_SELECTED = "n"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue