mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor(MeshLog): add fields for query optimization
- Adds `from_num` and `port_num` fields as indices to the `MeshLog` entity to improve query performance. - Sets default values for new columns for auto-migration and backward compatibility.
This commit is contained in:
parent
a075dfbd3a
commit
717c932ae2
7 changed files with 800 additions and 55 deletions
|
|
@ -9,6 +9,7 @@ import com.geeksville.mesh.android.Logging
|
|||
import com.google.protobuf.InvalidProtocolBufferException
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class Converters : Logging {
|
||||
@TypeConverter
|
||||
fun dataFromString(value: String): DataPacket {
|
||||
|
|
@ -22,6 +23,21 @@ class Converters : Logging {
|
|||
return json.encodeToString(DataPacket.serializer(), value)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun bytesToFromRadio(bytes: ByteArray): MeshProtos.FromRadio {
|
||||
return try {
|
||||
MeshProtos.FromRadio.parseFrom(bytes)
|
||||
} catch (ex: InvalidProtocolBufferException) {
|
||||
errormsg("bytesToFromRadio TypeConverter error:", ex)
|
||||
MeshProtos.FromRadio.getDefaultInstance()
|
||||
}
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromRadioToBytes(value: MeshProtos.FromRadio): ByteArray? {
|
||||
return value.toByteArray()
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun bytesToUser(bytes: ByteArray): MeshProtos.User {
|
||||
return try {
|
||||
|
|
|
|||
|
|
@ -26,17 +26,15 @@ class MeshLogRepository @Inject constructor(private val meshLogDaoLazy: dagger.L
|
|||
meshLogDao.getAllLogsInReceiveOrder(maxItems)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun getMeshPacketsFrom(nodeNum: Int) = meshLogDao.getAllLogs(MAX_MESH_PACKETS)
|
||||
.mapLatest { list -> list.mapNotNull { it.meshPacket }.filter { it.from == nodeNum } }
|
||||
.distinctUntilChanged()
|
||||
.flowOn(Dispatchers.IO)
|
||||
private fun parseTelemetryLog(log: MeshLog): Telemetry? =
|
||||
runCatching { Telemetry.parseFrom(log.fromRadio.packet.decoded.payload) }.getOrNull()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun getTelemetryFrom(nodeNum: Int) = getMeshPacketsFrom(nodeNum).mapLatest { list ->
|
||||
list.filter { it.hasDecoded() && it.decoded.portnum == Portnums.PortNum.TELEMETRY_APP }
|
||||
.mapNotNull { runCatching { Telemetry.parseFrom(it.decoded.payload) }.getOrNull() }
|
||||
}.flowOn(Dispatchers.IO)
|
||||
fun getTelemetryFrom(nodeNum: Int): Flow<List<Telemetry>> =
|
||||
meshLogDao.getLogsFrom(nodeNum, Portnums.PortNum.TELEMETRY_APP_VALUE, MAX_MESH_PACKETS)
|
||||
.distinctUntilChanged()
|
||||
.mapLatest { list -> list.mapNotNull(::parseTelemetryLog) }
|
||||
.flowOn(Dispatchers.IO)
|
||||
|
||||
suspend fun insert(log: MeshLog) = withContext(Dispatchers.IO) {
|
||||
meshLogDao.insert(log)
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@ import com.geeksville.mesh.database.entity.QuickChatAction
|
|||
AutoMigration (from = 8, to = 9),
|
||||
AutoMigration (from = 9, to = 10),
|
||||
AutoMigration (from = 10, to = 11),
|
||||
AutoMigration (from = 11, to = 12),
|
||||
],
|
||||
version = 11,
|
||||
version = 12,
|
||||
exportSchema = true,
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
|
|
|
|||
|
|
@ -9,16 +9,25 @@ import kotlinx.coroutines.flow.Flow
|
|||
@Dao
|
||||
interface MeshLogDao {
|
||||
|
||||
@Query("Select * from log order by received_date desc limit 0,:maxItem")
|
||||
@Query("SELECT * FROM log ORDER BY received_date DESC LIMIT 0,:maxItem")
|
||||
fun getAllLogs(maxItem: Int): Flow<List<MeshLog>>
|
||||
|
||||
@Query("Select * from log order by received_date asc limit 0,:maxItem")
|
||||
@Query("SELECT * FROM log ORDER BY received_date ASC LIMIT 0,:maxItem")
|
||||
fun getAllLogsInReceiveOrder(maxItem: Int): Flow<List<MeshLog>>
|
||||
|
||||
@Query(
|
||||
"""
|
||||
SELECT * FROM log
|
||||
WHERE from_num = :fromNum AND port_num = :portNum
|
||||
ORDER BY received_date DESC LIMIT 0,:maxItem
|
||||
"""
|
||||
)
|
||||
fun getLogsFrom(fromNum: Int, portNum: Int, maxItem: Int): Flow<List<MeshLog>>
|
||||
|
||||
@Insert
|
||||
fun insert(log: MeshLog)
|
||||
|
||||
@Query("DELETE from log")
|
||||
@Query("DELETE FROM log")
|
||||
fun deleteAll()
|
||||
|
||||
}
|
||||
|
|
@ -2,18 +2,30 @@ package com.geeksville.mesh.database.entity
|
|||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.geeksville.mesh.MeshProtos.FromRadio
|
||||
import com.geeksville.mesh.Portnums
|
||||
import com.google.protobuf.TextFormat
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
@Entity(tableName = "log")
|
||||
data class MeshLog(@PrimaryKey val uuid: String,
|
||||
@ColumnInfo(name = "type") val message_type: String,
|
||||
@ColumnInfo(name = "received_date") val received_date: Long,
|
||||
@ColumnInfo(name = "message") val raw_message: String
|
||||
@Entity(
|
||||
tableName = "log",
|
||||
indices = [
|
||||
Index(value = ["from_num"]),
|
||||
Index(value = ["port_num"]),
|
||||
],
|
||||
)
|
||||
data class MeshLog(
|
||||
@PrimaryKey val uuid: String,
|
||||
@ColumnInfo(name = "type") val message_type: String,
|
||||
@ColumnInfo(name = "received_date") val received_date: Long,
|
||||
@ColumnInfo(name = "message") val raw_message: String,
|
||||
@ColumnInfo(name = "from_num", defaultValue = "0") val fromNum: Int = 0,
|
||||
@ColumnInfo(name = "port_num", defaultValue = "0") val portNum: Int = 0,
|
||||
@ColumnInfo(name = "from_radio", typeAffinity = ColumnInfo.BLOB, defaultValue = "x''")
|
||||
val fromRadio: FromRadio = FromRadio.getDefaultInstance(),
|
||||
) {
|
||||
|
||||
val meshPacket: MeshProtos.MeshPacket?
|
||||
|
|
|
|||
|
|
@ -216,10 +216,13 @@ class MeshService : Service(), Logging {
|
|||
|
||||
if (p.packet.hasDecoded()) {
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"Packet",
|
||||
System.currentTimeMillis(),
|
||||
p.packet.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "Packet",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = p.packet.toString(),
|
||||
fromNum = p.packet.from,
|
||||
portNum = p.packet.decoded.portnumValue,
|
||||
fromRadio = fromRadio { packet = p.packet },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
}
|
||||
|
|
@ -1061,10 +1064,13 @@ class MeshService : Service(), Logging {
|
|||
// debug("Recieved: $packet")
|
||||
if (packet.hasDecoded()) {
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"Packet",
|
||||
System.currentTimeMillis(),
|
||||
packet.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "Packet",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = packet.toString(),
|
||||
fromNum = packet.from,
|
||||
portNum = packet.decoded.portnumValue,
|
||||
fromRadio = fromRadio { this.packet = packet },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
|
|
@ -1320,10 +1326,11 @@ class MeshService : Service(), Logging {
|
|||
private fun handleDeviceConfig(config: ConfigProtos.Config) {
|
||||
debug("Received config ${config.toOneLineString()}")
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"Config ${config.payloadVariantCase}",
|
||||
System.currentTimeMillis(),
|
||||
config.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "Config ${config.payloadVariantCase}",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = config.toString(),
|
||||
fromRadio = fromRadio { this.config = config },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
setLocalConfig(config)
|
||||
|
|
@ -1334,10 +1341,11 @@ class MeshService : Service(), Logging {
|
|||
private fun handleModuleConfig(config: ModuleConfigProtos.ModuleConfig) {
|
||||
debug("Received moduleConfig ${config.toOneLineString()}")
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"ModuleConfig ${config.payloadVariantCase}",
|
||||
System.currentTimeMillis(),
|
||||
config.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "ModuleConfig ${config.payloadVariantCase}",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = config.toString(),
|
||||
fromRadio = fromRadio { moduleConfig = config },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
setLocalModuleConfig(config)
|
||||
|
|
@ -1358,10 +1366,11 @@ class MeshService : Service(), Logging {
|
|||
private fun handleChannel(ch: ChannelProtos.Channel) {
|
||||
debug("Received channel ${ch.index}")
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"Channel",
|
||||
System.currentTimeMillis(),
|
||||
ch.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "Channel",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = ch.toString(),
|
||||
fromRadio = fromRadio { channel = ch },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
if (ch.role != ChannelProtos.Channel.Role.DISABLED) updateChannelSettings(ch)
|
||||
|
|
@ -1404,10 +1413,11 @@ class MeshService : Service(), Logging {
|
|||
debug("Received nodeinfo num=${info.num}, hasUser=${info.hasUser()}, hasPosition=${info.hasPosition()}, hasDeviceMetrics=${info.hasDeviceMetrics()}")
|
||||
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"NodeInfo",
|
||||
System.currentTimeMillis(),
|
||||
info.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "NodeInfo",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = info.toString(),
|
||||
fromRadio = fromRadio { nodeInfo = info },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
|
|
@ -1465,10 +1475,11 @@ class MeshService : Service(), Logging {
|
|||
*/
|
||||
private fun handleMyInfo(myInfo: MeshProtos.MyNodeInfo) {
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"MyNodeInfo",
|
||||
System.currentTimeMillis(),
|
||||
myInfo.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "MyNodeInfo",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = myInfo.toString(),
|
||||
fromRadio = fromRadio { this.myInfo = myInfo },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
|
|
@ -1488,10 +1499,11 @@ class MeshService : Service(), Logging {
|
|||
private fun handleMetadata(metadata: MeshProtos.DeviceMetadata) {
|
||||
debug("Received deviceMetadata ${metadata.toOneLineString()}")
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"DeviceMetadata",
|
||||
System.currentTimeMillis(),
|
||||
metadata.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "DeviceMetadata",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = metadata.toString(),
|
||||
fromRadio = fromRadio { this.metadata = metadata },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
|
|
@ -1561,10 +1573,11 @@ class MeshService : Service(), Logging {
|
|||
if (configCompleteId == configNonce) {
|
||||
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"ConfigComplete",
|
||||
System.currentTimeMillis(),
|
||||
configCompleteId.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "ConfigComplete",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = configCompleteId.toString(),
|
||||
fromRadio = fromRadio { this.configCompleteId = configCompleteId },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue