mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-05-18 11:46:28 -04:00
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:
@@ -78,12 +78,11 @@ class MessagePersistenceHandler(
|
||||
|
||||
override fun rememberDataPacket(dataPacket: DataPacket, myNodeNum: Int, updateNotification: Boolean) {
|
||||
if (dataPacket.dataType !in rememberDataType) return
|
||||
val fromLocal =
|
||||
dataPacket.from == DataPacket.ID_LOCAL || dataPacket.from == DataPacket.nodeNumToDefaultId(myNodeNum)
|
||||
val toBroadcast = dataPacket.to == DataPacket.ID_BROADCAST
|
||||
val fromLocal = dataPacket.from == DataPacket.LOCAL || dataPacket.from == myNodeNum
|
||||
val toBroadcast = dataPacket.to == DataPacket.BROADCAST
|
||||
val contactId = if (fromLocal || toBroadcast) dataPacket.to else dataPacket.from
|
||||
|
||||
val contactKey = "${dataPacket.channel}$contactId"
|
||||
val contactKey = "${dataPacket.channel}${DataPacket.nodeNumToId(contactId)}"
|
||||
|
||||
scope.handledLaunch {
|
||||
packetRepository.value.apply {
|
||||
@@ -116,7 +115,7 @@ class MessagePersistenceHandler(
|
||||
|
||||
@Suppress("ReturnCount")
|
||||
private suspend fun PacketRepository.shouldFilterMessage(dataPacket: DataPacket, contactKey: String): Boolean {
|
||||
val isIgnored = nodeRepository.nodeDBbyID[dataPacket.from]?.isIgnored == true
|
||||
val isIgnored = nodeRepository.nodeDBbyNum.value[dataPacket.from]?.isIgnored == true
|
||||
if (isIgnored) return true
|
||||
|
||||
if (dataPacket.dataType != PortNum.TEXT_MESSAGE_APP.value) return false
|
||||
@@ -130,7 +129,7 @@ class MessagePersistenceHandler(
|
||||
updateNotification: Boolean,
|
||||
) {
|
||||
val conversationMuted = packetRepository.value.getContactSettings(contactKey).isMuted
|
||||
val nodeMuted = nodeRepository.nodeDBbyID[dataPacket.from]?.isMuted == true
|
||||
val nodeMuted = nodeRepository.nodeDBbyNum.value[dataPacket.from]?.isMuted == true
|
||||
val isSilent = conversationMuted || nodeMuted
|
||||
if (dataPacket.dataType == PortNum.ALERT_APP.value && !isSilent) {
|
||||
scope.launch {
|
||||
@@ -149,11 +148,10 @@ class MessagePersistenceHandler(
|
||||
}
|
||||
|
||||
private suspend fun getSenderName(packet: DataPacket): String {
|
||||
if (packet.from == DataPacket.ID_LOCAL) {
|
||||
val myId = nodeRepository.getMyId()
|
||||
return nodeRepository.nodeDBbyID[myId]?.user?.long_name ?: getStringSuspend(Res.string.unknown_username)
|
||||
if (packet.from == DataPacket.LOCAL) {
|
||||
return nodeRepository.ourNodeInfo.value?.user?.long_name ?: getStringSuspend(Res.string.unknown_username)
|
||||
}
|
||||
return nodeRepository.nodeDBbyID[packet.from]?.user?.long_name ?: getStringSuspend(Res.string.unknown_username)
|
||||
return nodeRepository.nodeDBbyNum.value[packet.from]?.user?.long_name ?: getStringSuspend(Res.string.unknown_username)
|
||||
}
|
||||
|
||||
private suspend fun updateNotification(contactKey: String, dataPacket: DataPacket, isSilent: Boolean) {
|
||||
@@ -161,7 +159,7 @@ class MessagePersistenceHandler(
|
||||
PortNum.TEXT_MESSAGE_APP.value -> {
|
||||
val message = dataPacket.text!!
|
||||
val channelName =
|
||||
if (dataPacket.to == DataPacket.ID_BROADCAST) {
|
||||
if (dataPacket.to == DataPacket.BROADCAST) {
|
||||
radioConfigRepository.channelSetFlow.first().settings.getOrNull(dataPacket.channel)?.name
|
||||
} else {
|
||||
null
|
||||
@@ -170,7 +168,7 @@ class MessagePersistenceHandler(
|
||||
contactKey,
|
||||
getSenderName(dataPacket),
|
||||
message,
|
||||
dataPacket.to == DataPacket.ID_BROADCAST,
|
||||
dataPacket.to == DataPacket.BROADCAST,
|
||||
channelName,
|
||||
isSilent,
|
||||
)
|
||||
|
||||
@@ -97,7 +97,7 @@ class StoreForwardPacketHandlerImpl(
|
||||
encryptedPayload = sfpp.message.toByteArray(),
|
||||
to =
|
||||
if (sfpp.encapsulated_to == 0) {
|
||||
DataPacket.NODENUM_BROADCAST
|
||||
DataPacket.BROADCAST
|
||||
} else {
|
||||
sfpp.encapsulated_to
|
||||
},
|
||||
@@ -174,7 +174,7 @@ class StoreForwardPacketHandlerImpl(
|
||||
|
||||
s.text != null -> {
|
||||
if (s.rr == StoreAndForward.RequestResponse.ROUTER_TEXT_BROADCAST) {
|
||||
dataPacket.to = DataPacket.ID_BROADCAST
|
||||
dataPacket.to = DataPacket.BROADCAST
|
||||
}
|
||||
val u = dataPacket.copy(bytes = s.text, dataType = PortNum.TEXT_MESSAGE_APP.value)
|
||||
dataHandler.value.rememberDataPacket(u, myNodeNum)
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.meshtastic.core.data.radio
|
||||
|
||||
import co.touchlab.kermit.Logger
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import org.koin.core.annotation.Single
|
||||
import org.meshtastic.core.di.CoroutineDispatchers
|
||||
import org.meshtastic.core.model.MessageStatus
|
||||
import org.meshtastic.core.repository.PacketRepository
|
||||
import org.meshtastic.sdk.MessageHandle
|
||||
import org.meshtastic.sdk.SendState
|
||||
|
||||
/**
|
||||
* Tracks in-flight message delivery via SDK [MessageHandle]s.
|
||||
* Maps SDK [SendState] transitions to app [MessageStatus] and persists updates.
|
||||
*/
|
||||
@Single
|
||||
class MessageDeliveryTracker(
|
||||
private val packetRepository: Lazy<PacketRepository>,
|
||||
dispatchers: CoroutineDispatchers,
|
||||
) {
|
||||
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)
|
||||
private val activeHandles = mutableMapOf<Int, MessageHandle>()
|
||||
private val activeHandlesMutex = Mutex()
|
||||
|
||||
/**
|
||||
* Begin tracking a [MessageHandle] for the given packet ID.
|
||||
* Observes state transitions and updates message status in the repository.
|
||||
*/
|
||||
fun track(packetId: Int, handle: MessageHandle) {
|
||||
scope.launch {
|
||||
activeHandlesMutex.withLock {
|
||||
activeHandles[packetId] = handle
|
||||
}
|
||||
|
||||
val repository = packetRepository.value
|
||||
handle.state
|
||||
.onEach { state ->
|
||||
val status = mapSendState(state)
|
||||
Logger.d { "[DeliveryTracker] Packet $packetId → $status" }
|
||||
repository.updateMessageStatus(packetId, status)
|
||||
}
|
||||
.first { state ->
|
||||
val terminal = state.isTerminal()
|
||||
if (terminal) {
|
||||
activeHandlesMutex.withLock {
|
||||
if (activeHandles[packetId] === handle) {
|
||||
activeHandles.remove(packetId)
|
||||
}
|
||||
}
|
||||
}
|
||||
terminal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapSendState(state: SendState): MessageStatus = when (state) {
|
||||
SendState.Queued -> MessageStatus.QUEUED
|
||||
SendState.Sent -> MessageStatus.ENROUTE
|
||||
SendState.Acked -> MessageStatus.DELIVERED
|
||||
SendState.Delivered -> MessageStatus.DELIVERED
|
||||
is SendState.Failed -> MessageStatus.ERROR
|
||||
}
|
||||
|
||||
private fun SendState.isTerminal(): Boolean =
|
||||
this is SendState.Acked || this is SendState.Delivered || this is SendState.Failed
|
||||
}
|
||||
@@ -23,9 +23,14 @@ import okio.ByteString.Companion.toByteString
|
||||
import org.koin.core.annotation.Single
|
||||
import org.meshtastic.core.model.ConnectionState
|
||||
import org.meshtastic.core.model.DataPacket
|
||||
import org.meshtastic.core.model.DataRequester
|
||||
import org.meshtastic.core.model.DeviceAdmin
|
||||
import org.meshtastic.core.model.DeviceControl
|
||||
import org.meshtastic.core.model.MeshActivity
|
||||
import org.meshtastic.core.model.MessageSender
|
||||
import org.meshtastic.core.model.Position
|
||||
import org.meshtastic.core.model.RadioController
|
||||
import org.meshtastic.core.model.RemoteAdmin
|
||||
import org.meshtastic.core.repository.MeshLocationManager
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.repository.ServiceRepository
|
||||
@@ -55,13 +60,23 @@ import org.meshtastic.sdk.RadioClient
|
||||
* **State distribution:** Handled by [SdkStateBridge], which feeds SDK flows into
|
||||
* [ServiceRepository] and [org.meshtastic.core.repository.NodeRepository].
|
||||
*/
|
||||
@Single(binds = [RadioController::class])
|
||||
@Single(
|
||||
binds = [
|
||||
RadioController::class,
|
||||
MessageSender::class,
|
||||
DeviceAdmin::class,
|
||||
RemoteAdmin::class,
|
||||
DeviceControl::class,
|
||||
DataRequester::class,
|
||||
],
|
||||
)
|
||||
@Suppress("TooManyFunctions", "LongParameterList")
|
||||
class SdkRadioController(
|
||||
private val accessor: RadioClientAccessor,
|
||||
private val serviceRepository: ServiceRepository,
|
||||
private val nodeRepository: NodeRepository,
|
||||
private val locationManager: MeshLocationManager,
|
||||
private val deliveryTracker: MessageDeliveryTracker,
|
||||
) : RadioController {
|
||||
|
||||
private val packetIdCounter = atomic(1)
|
||||
@@ -95,13 +110,14 @@ class SdkRadioController(
|
||||
Logger.w { "sendMessage: no client, dropping packet" }
|
||||
return
|
||||
}
|
||||
val destNum = when (packet.to) {
|
||||
null, DataPacket.ID_BROADCAST -> DataPacket.NODENUM_BROADCAST
|
||||
else -> DataPacket.idToDefaultNodeNum(packet.to?.removePrefix("!")) ?: DataPacket.NODENUM_BROADCAST
|
||||
}
|
||||
val destNum = packet.to
|
||||
val packetId = packet.id.takeIf { it != 0 } ?: getPacketId()
|
||||
val meshPacket = MeshPacket(
|
||||
id = packetId,
|
||||
to = destNum,
|
||||
channel = packet.channel,
|
||||
want_ack = packet.wantAck,
|
||||
hop_limit = packet.hopLimit,
|
||||
decoded = Data(
|
||||
portnum = PortNum.fromValue(packet.dataType) ?: PortNum.UNKNOWN_APP,
|
||||
payload = packet.bytes ?: okio.ByteString.EMPTY,
|
||||
@@ -109,7 +125,8 @@ class SdkRadioController(
|
||||
),
|
||||
)
|
||||
try {
|
||||
c.send(meshPacket)
|
||||
val handle = c.send(meshPacket)
|
||||
deliveryTracker.track(packetId, handle)
|
||||
serviceRepository.emitMeshActivity(MeshActivity.Send)
|
||||
} catch (e: Exception) {
|
||||
Logger.e(e) { "sendMessage failed" }
|
||||
|
||||
@@ -27,10 +27,12 @@ import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.koin.core.annotation.Single
|
||||
import org.meshtastic.core.common.util.nowSeconds
|
||||
import org.meshtastic.core.di.CoroutineDispatchers
|
||||
import org.meshtastic.core.model.ConnectionState as AppConnectionState
|
||||
import org.meshtastic.core.model.DataPacket
|
||||
import org.meshtastic.core.model.RadioController
|
||||
import org.meshtastic.core.model.util.onlineTimeThreshold
|
||||
import org.meshtastic.core.model.service.ServiceAction
|
||||
import org.meshtastic.core.repository.MeshLocationManager
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
@@ -102,6 +104,26 @@ class SdkStateBridge(
|
||||
is NodeChange.Added -> nodeRepository.installNodeInfo(change.node, withBroadcast = true)
|
||||
is NodeChange.Updated -> nodeRepository.installNodeInfo(change.node, withBroadcast = true)
|
||||
is NodeChange.Removed -> nodeRepository.removeByNodenum(change.nodeId.raw)
|
||||
is NodeChange.WentOffline -> {
|
||||
val nodeNum = change.nodeId.raw
|
||||
Logger.d {
|
||||
"[SdkBridge] Node ${DataPacket.nodeNumToDefaultId(nodeNum)} went offline (last heard: ${change.lastHeard})"
|
||||
}
|
||||
if (nodeRepository.nodeDBbyNodeNum.containsKey(nodeNum)) {
|
||||
nodeRepository.updateNode(nodeNum) { node ->
|
||||
node.copy(lastHeard = minOf(node.lastHeard, change.lastHeard, onlineTimeThreshold()))
|
||||
}
|
||||
}
|
||||
}
|
||||
is NodeChange.CameOnline -> {
|
||||
val nodeNum = change.nodeId.raw
|
||||
Logger.d { "[SdkBridge] Node ${DataPacket.nodeNumToDefaultId(nodeNum)} came online" }
|
||||
if (nodeRepository.nodeDBbyNodeNum.containsKey(nodeNum)) {
|
||||
nodeRepository.updateNode(nodeNum) { node ->
|
||||
node.copy(lastHeard = maxOf(node.lastHeard, nowSeconds.toInt()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
@@ -230,8 +252,7 @@ class SdkStateBridge(
|
||||
is ServiceAction.Reaction -> {
|
||||
val channel = action.contactKey[0].digitToInt()
|
||||
val destId = action.contactKey.substring(1)
|
||||
val destNum = DataPacket.idToDefaultNodeNum(destId.removePrefix("!"))
|
||||
?: DataPacket.NODENUM_BROADCAST
|
||||
val destNum = runCatching { DataPacket.parseNodeNum(destId) }.getOrDefault(DataPacket.BROADCAST)
|
||||
client.send(
|
||||
MeshPacket(
|
||||
to = destNum,
|
||||
@@ -288,12 +309,15 @@ class SdkStateBridge(
|
||||
companion object {
|
||||
private const val EMOJI_INDICATOR = 1
|
||||
|
||||
fun mapConnectionState(sdkState: SdkConnectionState): AppConnectionState = when (sdkState) {
|
||||
private fun mapConnectionState(sdkState: SdkConnectionState): AppConnectionState = when (sdkState) {
|
||||
is SdkConnectionState.Disconnected -> AppConnectionState.Disconnected
|
||||
is SdkConnectionState.Connecting -> AppConnectionState.Connecting
|
||||
is SdkConnectionState.Configuring -> AppConnectionState.Connecting
|
||||
is SdkConnectionState.Connecting -> AppConnectionState.Connecting(attempt = sdkState.attempt)
|
||||
is SdkConnectionState.Configuring -> AppConnectionState.Configuring(
|
||||
phase = sdkState.phase.name,
|
||||
progress = sdkState.progress,
|
||||
)
|
||||
is SdkConnectionState.Connected -> AppConnectionState.Connected
|
||||
is SdkConnectionState.Reconnecting -> AppConnectionState.DeviceSleep
|
||||
is SdkConnectionState.Reconnecting -> AppConnectionState.Reconnecting(attempt = sdkState.attempt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,27 +352,22 @@ class PacketRepositoryImpl(
|
||||
val dao = dbManager.currentDb.value.packetDao()
|
||||
val packets = findPacketsWithIdInternal(packetId)
|
||||
val reactions = findReactionsWithIdInternal(packetId)
|
||||
val fromId = DataPacket.nodeNumToDefaultId(from)
|
||||
val fromId = from
|
||||
val fromIdString = DataPacket.nodeNumToId(from)
|
||||
val isFromLocalNode = myNodeNum != null && from == myNodeNum
|
||||
val toId =
|
||||
if (to == 0 || to == DataPacket.NODENUM_BROADCAST) {
|
||||
DataPacket.ID_BROADCAST
|
||||
} else {
|
||||
DataPacket.nodeNumToDefaultId(to)
|
||||
}
|
||||
val toNodeNum = if (to == 0 || to == DataPacket.BROADCAST) DataPacket.BROADCAST else to
|
||||
val toId = DataPacket.nodeNumToId(toNodeNum)
|
||||
|
||||
val hashByteString = hash.toByteString()
|
||||
|
||||
packets.forEach { packet ->
|
||||
// For sent messages, from is stored as ID_LOCAL, but SFPP packet has node number
|
||||
val fromMatches =
|
||||
packet.data.from == fromId || (isFromLocalNode && packet.data.from == DataPacket.ID_LOCAL)
|
||||
val fromMatches = packet.data.from == fromId || (isFromLocalNode && packet.data.from == DataPacket.LOCAL)
|
||||
co.touchlab.kermit.Logger.d {
|
||||
"SFPP match check: packetFrom=${packet.data.from} fromId=$fromId " +
|
||||
"isFromLocal=$isFromLocalNode fromMatches=$fromMatches " +
|
||||
"packetTo=${packet.data.to} toId=$toId toMatches=${packet.data.to == toId}"
|
||||
"packetTo=${packet.data.to} toId=$toNodeNum toMatches=${packet.data.to == toNodeNum}"
|
||||
}
|
||||
if (fromMatches && packet.data.to == toId) {
|
||||
if (fromMatches && packet.data.to == toNodeNum) {
|
||||
// If it's already confirmed, don't downgrade it to routing
|
||||
if (packet.data.status == MessageStatus.SFPP_CONFIRMED && status == MessageStatus.SFPP_ROUTING) {
|
||||
return@forEach
|
||||
@@ -385,8 +380,7 @@ class PacketRepositoryImpl(
|
||||
|
||||
reactions.forEach { reaction ->
|
||||
val reactionFrom = reaction.userId
|
||||
// For sent reactions, from is stored as ID_LOCAL, but SFPP packet has node number
|
||||
val fromMatches = reactionFrom == fromId || (isFromLocalNode && reactionFrom == DataPacket.ID_LOCAL)
|
||||
val fromMatches = reactionFrom == fromIdString || (isFromLocalNode && reactionFrom == DataPacket.nodeNumToId(DataPacket.LOCAL))
|
||||
|
||||
val toMatches = reaction.to == toId
|
||||
|
||||
|
||||
@@ -125,9 +125,9 @@ class SdkNodeRepositoryImpl(
|
||||
|
||||
override fun getNode(userId: String): Node =
|
||||
_nodeDBbyNum.value.values.find { it.user.id == userId }
|
||||
?: Node(num = DataPacket.idToDefaultNodeNum(userId) ?: 0, user = getUser(userId))
|
||||
?: Node(num = runCatching { DataPacket.parseNodeNum(userId) }.getOrDefault(0), user = getUser(userId))
|
||||
|
||||
override fun getUser(nodeNum: Int): User = getUser(DataPacket.nodeNumToDefaultId(nodeNum))
|
||||
override fun getUser(nodeNum: Int): User = getUser(DataPacket.nodeNumToId(nodeNum))
|
||||
|
||||
private val last4 = 4
|
||||
|
||||
@@ -138,13 +138,13 @@ class SdkNodeRepositoryImpl(
|
||||
}
|
||||
val fallbackId = userId.takeLast(last4)
|
||||
val defaultLong =
|
||||
if (userId == DataPacket.ID_LOCAL) {
|
||||
if (userId == DataPacket.nodeNumToId(DataPacket.LOCAL)) {
|
||||
ourNodeInfo.value?.user?.long_name?.takeIf { it.isNotBlank() } ?: "Local"
|
||||
} else {
|
||||
"Meshtastic $fallbackId"
|
||||
}
|
||||
val defaultShort =
|
||||
if (userId == DataPacket.ID_LOCAL) {
|
||||
if (userId == DataPacket.nodeNumToId(DataPacket.LOCAL)) {
|
||||
ourNodeInfo.value?.user?.short_name?.takeIf { it.isNotBlank() } ?: "Local"
|
||||
} else {
|
||||
fallbackId
|
||||
@@ -408,8 +408,8 @@ class SdkNodeRepositoryImpl(
|
||||
|
||||
// ── NodeIdLookup ────────────────────────────────────────────────────────
|
||||
|
||||
override fun toNodeID(nodeNum: Int): String = if (nodeNum == DataPacket.NODENUM_BROADCAST) {
|
||||
DataPacket.ID_BROADCAST
|
||||
override fun toNodeID(nodeNum: Int): String = if (nodeNum == DataPacket.BROADCAST) {
|
||||
DataPacket.nodeNumToId(DataPacket.BROADCAST)
|
||||
} else {
|
||||
_nodeDBbyNum.value[nodeNum]?.user?.id ?: DataPacket.nodeNumToDefaultId(nodeNum)
|
||||
}
|
||||
|
||||
@@ -198,8 +198,8 @@ class SdkNodeRepositoryImplTest {
|
||||
|
||||
@Test
|
||||
fun `toNodeID returns broadcast ID for broadcast nodeNum`() {
|
||||
val result = nodeRepository.toNodeID(DataPacket.NODENUM_BROADCAST)
|
||||
assertEquals(DataPacket.ID_BROADCAST, result)
|
||||
val result = nodeRepository.toNodeID(DataPacket.BROADCAST)
|
||||
assertEquals(DataPacket.nodeNumToId(DataPacket.BROADCAST), result)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -86,8 +86,8 @@ class StoreForwardPacketHandlerImplTest {
|
||||
private fun makeDataPacket(from: Int): DataPacket = DataPacket(
|
||||
id = 1,
|
||||
time = 1700000000000L,
|
||||
to = DataPacket.ID_BROADCAST,
|
||||
from = DataPacket.nodeNumToDefaultId(from),
|
||||
to = DataPacket.BROADCAST,
|
||||
from = from,
|
||||
bytes = null,
|
||||
dataType = PortNum.STORE_FORWARD_APP.value,
|
||||
)
|
||||
|
||||
@@ -75,8 +75,8 @@ class TelemetryPacketHandlerImplTest {
|
||||
private fun makeDataPacket(from: Int): DataPacket = DataPacket(
|
||||
id = 1,
|
||||
time = 1700000000000L,
|
||||
to = DataPacket.ID_BROADCAST,
|
||||
from = DataPacket.nodeNumToDefaultId(from),
|
||||
to = DataPacket.BROADCAST,
|
||||
from = from,
|
||||
bytes = null,
|
||||
dataType = PortNum.TELEMETRY_APP.value,
|
||||
)
|
||||
|
||||
@@ -53,7 +53,7 @@ abstract class CommonPacketRepositoryTest {
|
||||
// Set the current node number so PacketRepositoryImpl can pass it to queries
|
||||
nodeRepository.setMyNodeInfo(org.meshtastic.core.testing.TestDataFactory.createMyNodeInfo(myNodeNum = myNodeNum))
|
||||
|
||||
val packet = DataPacket(to = "0!ffffffff", bytes = okio.ByteString.EMPTY, dataType = 1, id = 123)
|
||||
val packet = DataPacket(to = DataPacket.BROADCAST, bytes = okio.ByteString.EMPTY, dataType = 1, id = 123)
|
||||
|
||||
repository.savePacket(myNodeNum, contact, packet, 1000L)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user