create Room database for DataPacket

This commit is contained in:
andrekir
2022-09-14 01:54:13 -03:00
parent 9427eec72f
commit ab7bf4922b
8 changed files with 168 additions and 2 deletions

View File

@@ -0,0 +1,33 @@
package com.geeksville.mesh.database
import androidx.room.TypeConverter
import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.MeshProtos.MeshPacket
import com.google.protobuf.TextFormat
import kotlinx.serialization.json.Json
class Converters {
@TypeConverter
fun dataFromString(value: String): DataPacket {
val json = Json { isLenient = true }
return json.decodeFromString(DataPacket.serializer(), value)
}
@TypeConverter
fun dataToString(value: DataPacket): String {
val json = Json { isLenient = true }
return json.encodeToString(DataPacket.serializer(), value)
}
@TypeConverter
fun protoFromString(value: String): MeshPacket {
val builder = MeshPacket.newBuilder()
TextFormat.getParser().merge(value, builder)
return builder.build()
}
@TypeConverter
fun protoToString(value: MeshPacket): String {
return value.toString()
}
}

View File

@@ -2,6 +2,7 @@ package com.geeksville.mesh.database
import android.app.Application
import com.geeksville.mesh.database.dao.MeshLogDao
import com.geeksville.mesh.database.dao.PacketDao
import com.geeksville.mesh.database.dao.QuickChatActionDao
import dagger.Module
import dagger.Provides
@@ -17,6 +18,11 @@ class DatabaseModule {
fun provideDatabase(app: Application): MeshtasticDatabase =
MeshtasticDatabase.getDatabase(app)
@Provides
fun providePacketDao(database: MeshtasticDatabase): PacketDao {
return database.packetDao()
}
@Provides
fun provideMeshLogDao(database: MeshtasticDatabase): MeshLogDao {
return database.meshLogDao()

View File

@@ -4,13 +4,18 @@ import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import com.geeksville.mesh.database.dao.PacketDao
import com.geeksville.mesh.database.dao.MeshLogDao
import com.geeksville.mesh.database.dao.QuickChatActionDao
import com.geeksville.mesh.database.entity.MeshLog
import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.database.entity.QuickChatAction
@Database(entities = [MeshLog::class, QuickChatAction::class], version = 3, exportSchema = false)
@Database(entities = [Packet::class, MeshLog::class, QuickChatAction::class], version = 3, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MeshtasticDatabase : RoomDatabase() {
abstract fun packetDao(): PacketDao
abstract fun meshLogDao(): MeshLogDao
abstract fun quickChatActionDao(): QuickChatActionDao

View File

@@ -0,0 +1,34 @@
package com.geeksville.mesh.database
import com.geeksville.mesh.database.dao.PacketDao
import com.geeksville.mesh.database.entity.Packet
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
import javax.inject.Inject
class PacketRepository @Inject constructor(private val packetDaoLazy: dagger.Lazy<PacketDao>) {
private val packetDao by lazy {
packetDaoLazy.get()
}
suspend fun getAll(): Flow<List<Packet>> = withContext(Dispatchers.IO) {
packetDao.getAllPackets()
}
suspend fun insert(packet: Packet) = withContext(Dispatchers.IO) {
packetDao.insert(packet)
}
suspend fun deleteAll() = withContext(Dispatchers.IO) {
packetDao.deleteAll()
}
suspend fun delete(packet: Packet) = withContext(Dispatchers.IO) {
packetDao.delete(packet)
}
suspend fun update(packet: Packet) = withContext(Dispatchers.IO) {
packetDao.update(packet)
}
}

View File

@@ -0,0 +1,34 @@
package com.geeksville.mesh.database.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Update
import androidx.room.Query
import androidx.room.Transaction
import com.geeksville.mesh.database.entity.Packet
import kotlinx.coroutines.flow.Flow
@Dao
interface PacketDao {
@Query("Select * from packet order by received_time asc")
fun getAllPackets(): Flow<List<Packet>>
@Insert
fun insert(packet: Packet)
@Query("Delete from packet")
fun deleteAll()
@Query("Delete from packet where uuid=:uuid")
fun _delete(uuid: Long)
@Transaction
fun delete(packet: Packet) {
_delete(packet.uuid)
}
@Update
fun update(packet: Packet)
}

View File

@@ -0,0 +1,19 @@
package com.geeksville.mesh.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.MessageStatus
@Entity(tableName = "packet")
data class Packet(
@PrimaryKey(autoGenerate = true) val uuid: Long,
@ColumnInfo(name = "port_num") val port_num: Int,
@ColumnInfo(name = "contact_id") val contact_id: String?,
@ColumnInfo(name = "channel") val channel: Int,
@ColumnInfo(name = "status") val status: MessageStatus = MessageStatus.UNKNOWN,
@ColumnInfo(name = "received_time") val received_time: Long,
@ColumnInfo(name = "packet") val packet: DataPacket
) {
}

View File

@@ -16,9 +16,11 @@ import com.geeksville.mesh.*
import com.geeksville.mesh.ConfigProtos.Config
import com.geeksville.mesh.database.MeshLogRepository
import com.geeksville.mesh.database.QuickChatActionRepository
import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.database.entity.MeshLog
import com.geeksville.mesh.database.entity.QuickChatAction
import com.geeksville.mesh.LocalOnlyProtos.LocalConfig
import com.geeksville.mesh.database.PacketRepository
import com.geeksville.mesh.repository.datastore.ChannelSetRepository
import com.geeksville.mesh.repository.datastore.LocalConfigRepository
import com.geeksville.mesh.service.MeshService
@@ -67,6 +69,7 @@ class UIViewModel @Inject constructor(
private val app: Application,
private val meshLogRepository: MeshLogRepository,
private val channelSetRepository: ChannelSetRepository,
private val packetRepository: PacketRepository,
private val localConfigRepository: LocalConfigRepository,
private val quickChatActionRepository: QuickChatActionRepository,
private val preferences: SharedPreferences
@@ -75,6 +78,9 @@ class UIViewModel @Inject constructor(
private val _meshLog = MutableStateFlow<List<MeshLog>>(emptyList())
val meshLog: StateFlow<List<MeshLog>> = _meshLog
private val _packets = MutableStateFlow<List<Packet>>(emptyList())
val packets: StateFlow<List<Packet>> = _packets
private val _localConfig = MutableStateFlow<LocalConfig>(LocalConfig.getDefaultInstance())
val localConfig: StateFlow<LocalConfig> = _localConfig
val config get() = _localConfig.value
@@ -91,6 +97,11 @@ class UIViewModel @Inject constructor(
_meshLog.value = logs
}
}
viewModelScope.launch {
packetRepository.getAll().collect { meshPackets ->
_packets.value = meshPackets
}
}
viewModelScope.launch {
localConfigRepository.localConfigFlow.collect { config ->
_localConfig.value = config

View File

@@ -16,7 +16,9 @@ import com.geeksville.mesh.MeshProtos.MeshPacket
import com.geeksville.mesh.MeshProtos.ToRadio
import com.geeksville.mesh.android.hasBackgroundPermission
import com.geeksville.mesh.database.MeshLogRepository
import com.geeksville.mesh.database.PacketRepository
import com.geeksville.mesh.database.entity.MeshLog
import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.model.DeviceVersion
import com.geeksville.mesh.repository.datastore.ChannelSetRepository
import com.geeksville.mesh.repository.datastore.LocalConfigRepository
@@ -49,6 +51,9 @@ class MeshService : Service(), Logging {
@Inject
lateinit var dispatchers: CoroutineDispatchers
@Inject
lateinit var packetRepository: Lazy<PacketRepository>
@Inject
lateinit var meshLogRepository: Lazy<MeshLogRepository>
@@ -614,7 +619,20 @@ class MeshService : Service(), Logging {
private fun rememberDataPacket(dataPacket: DataPacket) {
// Now that we use data packets for more things, we need to be choosier about what we keep. Since (currently - in the future less so)
// we only care about old text messages, we just store those...
if (dataPacket.dataType == Portnums.PortNum.TEXT_MESSAGE_APP_VALUE) {
if (dataPacket.dataType == Portnums.PortNum.WAYPOINT_APP_VALUE
|| dataPacket.dataType == Portnums.PortNum.TEXT_MESSAGE_APP_VALUE
) {
val packetToSave = Packet(
0L, // autoGenerated
dataPacket.dataType,
if (dataPacket.from == DataPacket.ID_LOCAL || dataPacket.to == DataPacket.ID_BROADCAST) dataPacket.to else dataPacket.from,
dataPacket.channel,
MessageStatus.RECEIVED,
System.currentTimeMillis(),
dataPacket
)
insertPacket(packetToSave)
// discard old messages if needed then add the new one
while (recentDataPackets.size > 100)
recentDataPackets.removeAt(0)
@@ -930,6 +948,12 @@ class MeshService : Service(), Logging {
}
}
private fun insertPacket(packet: Packet) {
serviceScope.handledLaunch {
packetRepository.get().insert(packet)
}
}
private fun insertMeshLog(packetToSave: MeshLog) {
serviceScope.handledLaunch {
// Do not log, because might contain PII