refactor(ble): Centralize BLE logic into a core module (#4550)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-02-20 06:41:52 -06:00 committed by GitHub
parent 7a68802bc2
commit 6bfa5b5f70
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
214 changed files with 3471 additions and 2405 deletions

View file

@ -31,13 +31,13 @@ import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.database.MeshtasticDatabase
import org.meshtastic.core.database.entity.MyNodeEntity
import org.meshtastic.core.database.entity.Packet
import org.meshtastic.core.database.entity.ReactionEntity
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.model.MessageStatus
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.proto.PortNum
@RunWith(AndroidJUnit4::class)

View file

@ -33,8 +33,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.model.util.nowMillis
import java.io.File
import java.security.MessageDigest
import javax.inject.Inject
@ -42,6 +42,7 @@ import javax.inject.Singleton
/** Manages per-device Room database instances for node data, with LRU eviction. */
@Singleton
@Suppress("TooManyFunctions")
class DatabaseManager @Inject constructor(private val app: Application, private val dispatchers: CoroutineDispatchers) {
val prefs: SharedPreferences = app.getSharedPreferences("db-manager-prefs", Context.MODE_PRIVATE)
private val managerScope = CoroutineScope(SupervisorJob() + dispatchers.default)
@ -115,6 +116,13 @@ class DatabaseManager @Inject constructor(private val app: Application, private
/** Execute [block] with the current DB instance. */
inline fun <T> withDb(block: (MeshtasticDatabase) -> T): T = block(currentDb.value)
/** Returns true if a database exists for the given device address. */
fun hasDatabaseFor(address: String?): Boolean {
if (address.isNullOrBlank() || address == "n") return false
val dbName = buildDbName(address)
return getDbFile(app, dbName) != null
}
private fun markLastUsed(dbName: String) {
prefs.edit().putLong(lastUsedKey(dbName), nowMillis).apply()
}

View file

@ -25,13 +25,13 @@ import androidx.room.Update
import androidx.room.Upsert
import kotlinx.coroutines.flow.Flow
import okio.ByteString
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.database.entity.ContactSettings
import org.meshtastic.core.database.entity.Packet
import org.meshtastic.core.database.entity.PacketEntity
import org.meshtastic.core.database.entity.ReactionEntity
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.model.MessageStatus
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.proto.ChannelSettings
@Suppress("TooManyFunctions")

View file

@ -20,9 +20,9 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.serialization.Serializable
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.model.DeviceHardware
import org.meshtastic.core.model.NetworkDeviceHardware
import org.meshtastic.core.model.util.nowMillis
@Serializable
@Entity(tableName = "device_hardware")

View file

@ -20,9 +20,9 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.serialization.Serializable
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.model.DeviceVersion
import org.meshtastic.core.model.NetworkFirmwareRelease
import org.meshtastic.core.model.util.nowMillis
@Serializable
@Entity(tableName = "firmware_release")

View file

@ -24,14 +24,14 @@ import androidx.room.PrimaryKey
import androidx.room.Relation
import okio.ByteString
import okio.ByteString.Companion.toByteString
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.common.util.nowSeconds
import org.meshtastic.core.database.model.Node
import org.meshtastic.core.model.DeviceMetrics
import org.meshtastic.core.model.EnvironmentMetrics
import org.meshtastic.core.model.MeshUser
import org.meshtastic.core.model.NodeInfo
import org.meshtastic.core.model.Position
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.core.model.util.nowSeconds
import org.meshtastic.core.model.util.onlineTimeThreshold
import org.meshtastic.proto.DeviceMetadata
import org.meshtastic.proto.HardwareModel

View file

@ -23,12 +23,12 @@ import androidx.room.Index
import androidx.room.PrimaryKey
import androidx.room.Relation
import okio.ByteString
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.database.model.Message
import org.meshtastic.core.database.model.Node
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.model.MessageStatus
import org.meshtastic.core.model.util.getShortDateTime
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.proto.User
data class PacketEntity(

View file

@ -27,11 +27,11 @@ import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.database.MeshtasticDatabase
import org.meshtastic.core.database.entity.MyNodeEntity
import org.meshtastic.core.database.entity.Packet
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.proto.ChannelSettings
import org.meshtastic.proto.PortNum
@ -150,7 +150,7 @@ class MigrationTest {
}
private suspend fun insertPacket(channel: Int, text: String) {
packetDao.insert(
val packet =
Packet(
uuid = 0L,
myNodeNum = 42424242,
@ -159,8 +159,8 @@ class MigrationTest {
received_time = nowMillis,
read = false,
data = DataPacket(to = DataPacket.ID_BROADCAST, channel = channel, text = text),
),
)
)
packetDao.insert(packet)
}
private suspend fun getAllPackets() = packetDao.getAllPackets(PortNum.TEXT_MESSAGE_APP.value).first()