fix #2062: Remap channels when rearranged (#3561)

This commit is contained in:
Dane Evans 2025-10-31 01:55:37 +11:00 committed by GitHub
parent 4f6140c1d6
commit 2b79590881
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 38 additions and 1 deletions

View file

@ -29,6 +29,7 @@ import org.meshtastic.core.database.entity.ReactionEntity
import org.meshtastic.core.database.model.Node
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.model.MessageStatus
import org.meshtastic.proto.ChannelProtos.ChannelSettings
import org.meshtastic.proto.Portnums.PortNum
import javax.inject.Inject
@ -103,4 +104,7 @@ class PacketRepository @Inject constructor(private val packetDaoLazy: Lazy<Packe
suspend fun insertReaction(reaction: ReactionEntity) = withContext(Dispatchers.IO) { packetDao.insert(reaction) }
suspend fun clearPacketDB() = withContext(Dispatchers.IO) { packetDao.deleteAll() }
suspend fun migrateChannelsByPSK(oldSettings: List<ChannelSettings>, newSettings: List<ChannelSettings>) =
packetDao.migrateChannelsByPSK(oldSettings, newSettings)
}

View file

@ -30,6 +30,7 @@ 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.proto.ChannelProtos.ChannelSettings
@Suppress("TooManyFunctions")
@Dao
@ -250,4 +251,29 @@ interface PacketDao {
@Query("DELETE FROM packet")
suspend fun deleteAll()
/**
* One-time migration: Remap all message DataPacket.channel indices to new mapping using PSK after a channel
* reorder. For each Packet (with port_num = 1), finds the old PSK then sets the channel index to the matching
* newSettings index. Skips if PSKs do not match or are missing.
*/
@Transaction
suspend fun migrateChannelsByPSK(oldSettings: List<ChannelSettings>, newSettings: List<ChannelSettings>) {
val pskToNewIndex = newSettings.mapIndexed { idx, ch -> ch.psk to idx }.toMap()
val allPackets = getAllUserPacketsForMigration()
for (packet in allPackets) {
val oldIndex = packet.data.channel
val oldPSK = oldSettings.getOrNull(oldIndex)?.psk
val newIndex = if (oldPSK != null) pskToNewIndex[oldPSK] else null
if (oldPSK != null && newIndex != null && oldIndex != newIndex) {
// Rebuild contact_key with the new index, keeping the rest unchanged
val oldKeySuffix = packet.contact_key.drop(1) // removes only the channelIndex prefix
val newContactKey = "$newIndex$oldKeySuffix"
update(packet.copy(contact_key = newContactKey, data = packet.data.copy(channel = newIndex)))
}
}
}
@Query("SELECT * FROM packet WHERE port_num = 1")
suspend fun getAllUserPacketsForMigration(): List<Packet>
}

View file

@ -49,6 +49,7 @@ import kotlinx.coroutines.withContext
import org.json.JSONObject
import org.meshtastic.core.data.repository.LocationRepository
import org.meshtastic.core.data.repository.NodeRepository
import org.meshtastic.core.data.repository.PacketRepository
import org.meshtastic.core.data.repository.RadioConfigRepository
import org.meshtastic.core.database.entity.MyNodeEntity
import org.meshtastic.core.database.model.Node
@ -108,6 +109,7 @@ constructor(
savedStateHandle: SavedStateHandle,
private val app: Application,
private val radioConfigRepository: RadioConfigRepository,
private val packetRepository: PacketRepository,
private val serviceRepository: ServiceRepository,
private val nodeRepository: NodeRepository,
private val locationRepository: LocationRepository,
@ -247,7 +249,12 @@ constructor(
val destNum = destNode.value?.num ?: return
getChannelList(new, old).forEach { setRemoteChannel(destNum, it) }
if (destNum == myNodeNum) viewModelScope.launch { radioConfigRepository.replaceAllSettings(new) }
if (destNum == myNodeNum) {
viewModelScope.launch {
packetRepository.migrateChannelsByPSK(old, new)
radioConfigRepository.replaceAllSettings(new)
}
}
_radioConfigState.update { it.copy(channelList = new) }
}