feat: rearchitect around SDK — decompose RadioController, simplify DataPacket, integrate SDK utilities

Android rearchitecture consuming meshtastic-sdk improvements:

A1 — ConnectionState Enrichment:
- Rich sealed interface with Connecting(attempt), Configuring(phase, progress), Reconnecting(attempt)
- SdkStateBridge maps SDK states preserving metadata

A2 — MessageHandle Integration:
- MessageDeliveryTracker: tracks delivery via SDK MessageHandle
- SdkRadioController captures handles on send

A3 — RadioController Decomposition:
- Split into 5 focused interfaces: MessageSender, DeviceAdmin, RemoteAdmin, DeviceControl, DataRequester
- RadioController extends all; SdkRadioController binds all via Koin

A4 — DataPacket Simplification:
- to/from fields changed from String? to Int (node numbers directly)
- Removed string ID parsing layer; added BROADCAST/LOCAL constants
- Updated ~40 consumer files across feature modules

A5 — SDK Utility Consumption:
- DeviceVersion, Capabilities, SfppHasher, LocationUtils delegate to SDK
- Removed duplicated protocol logic

A6 — Presence Events:
- SdkStateBridge handles NodeChange.WentOffline/CameOnline
- Updates node online status via repository

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
James Rich
2026-05-05 13:08:07 -05:00
parent 43ecd2eb73
commit e9cb439849
55 changed files with 573 additions and 558 deletions

View File

@@ -143,7 +143,7 @@ class MigrationTest {
contact_key = "$channel!broadcast",
received_time = nowMillis,
read = false,
data = DataPacket(to = DataPacket.ID_BROADCAST, channel = channel, text = text),
data = DataPacket(to = DataPacket.BROADCAST, channel = channel, text = text),
)
packetDao.insert(packet)
}

View File

@@ -37,8 +37,8 @@ data class PacketEntity(
val reactions: List<ReactionEntity> = emptyList(),
) {
suspend fun toMessage(getNode: suspend (userId: String?) -> Node) = with(packet) {
val node = getNode(data.from)
val isFromLocal = node.user.id == DataPacket.ID_LOCAL || (myNodeNum != 0 && node.num == myNodeNum)
val node = getNode(DataPacket.nodeNumToId(data.from))
val isFromLocal = data.from == DataPacket.LOCAL || (myNodeNum != 0 && data.from == myNodeNum)
Message(
uuid = uuid,
receivedTime = received_time,

View File

@@ -40,7 +40,7 @@ abstract class CommonPacketDaoTest {
private val myNodeNum = 42424242
private val testContactKeys = listOf("0${DataPacket.ID_BROADCAST}", "1!test1234")
private val testContactKeys = listOf("0${DataPacket.nodeNumToId(DataPacket.BROADCAST)}", "1!test1234")
private fun generateTestPackets(nodeNum: Int) = testContactKeys.flatMap { contactKey ->
List(SAMPLE_SIZE) {
@@ -53,7 +53,7 @@ abstract class CommonPacketDaoTest {
read = false,
data =
DataPacket(
to = DataPacket.ID_BROADCAST,
to = DataPacket.BROADCAST,
bytes = "Message $it!".encodeToByteArray().toByteString(),
dataType = PortNum.TEXT_MESSAGE_APP.value,
),
@@ -115,7 +115,7 @@ abstract class CommonPacketDaoTest {
val messages = packetDao.getMessagesFrom(myNodeNum, contactKey).first()
val packet = messages.first().packet.data
val packetWithId = packet.copy(id = 999, from = "!$myNodeNum")
val packetWithId = packet.copy(id = 999, from = myNodeNum)
val updatedRoomPacket = messages.first().packet.copy(data = packetWithId, packetId = 999)
packetDao.update(updatedRoomPacket)
@@ -136,7 +136,7 @@ abstract class CommonPacketDaoTest {
read = true,
data =
DataPacket(
to = DataPacket.ID_BROADCAST,
to = DataPacket.BROADCAST,
bytes = "Queued".encodeToByteArray().toByteString(),
dataType = PortNum.TEXT_MESSAGE_APP.value,
status = MessageStatus.QUEUED,
@@ -170,12 +170,12 @@ abstract class CommonPacketDaoTest {
uuid = 0L,
myNodeNum = myNodeNum,
port_num = PortNum.WAYPOINT_APP.value,
contact_key = "0${DataPacket.ID_BROADCAST}",
contact_key = "0${DataPacket.nodeNumToId(DataPacket.BROADCAST)}",
received_time = nowMillis,
read = true,
data =
DataPacket(
to = DataPacket.ID_BROADCAST,
to = DataPacket.BROADCAST,
bytes = "Waypoint".encodeToByteArray().toByteString(),
dataType = PortNum.WAYPOINT_APP.value,
),
@@ -208,7 +208,7 @@ abstract class CommonPacketDaoTest {
received_time = nowMillis + index,
read = false,
data = DataPacket(
to = DataPacket.ID_BROADCAST,
to = DataPacket.BROADCAST,
bytes = text.encodeToByteArray().toByteString(),
dataType = PortNum.TEXT_MESSAGE_APP.value,
),
@@ -227,7 +227,7 @@ abstract class CommonPacketDaoTest {
received_time = nowMillis + normalMessages.size + index,
read = true,
data = DataPacket(
to = DataPacket.ID_BROADCAST,
to = DataPacket.BROADCAST,
bytes = text.encodeToByteArray().toByteString(),
dataType = PortNum.TEXT_MESSAGE_APP.value,
),
@@ -265,7 +265,7 @@ abstract class CommonPacketDaoTest {
received_time = baseTime + id,
read = false,
data = DataPacket(
to = DataPacket.ID_BROADCAST,
to = DataPacket.BROADCAST,
bytes = "Chunk $id".encodeToByteArray().toByteString(),
dataType = PortNum.TEXT_MESSAGE_APP.value,
),