fix #209. don't ignore messages from nodes that only have partial nodeinfo

pull/239/head
Kevin Hester 2021-02-08 11:22:15 +08:00
rodzic 5deddf6547
commit 65e91c46d3
4 zmienionych plików z 58 dodań i 36 usunięć

Wyświetl plik

@ -126,6 +126,11 @@ data class DataPacket(
/** The Node ID for the local node - used for from when sender doesn't know our local node ID */
const val ID_LOCAL = "^local"
/// special broadcast address
const val NODENUM_BROADCAST = (0xffffffff).toInt()
fun nodeNumToDefaultId(n: Int): String = "!%08x".format(n)
override fun createFromParcel(parcel: Parcel): DataPacket {
return DataPacket(parcel)
}

Wyświetl plik

@ -49,9 +49,6 @@ class MeshService : Service(), Logging {
companion object : Logging {
/// special broadcast address
const val NODENUM_BROADCAST = (0xffffffff).toInt()
/// Intents broadcast by MeshService
@Deprecated(message = "Does not filter by port number. For legacy reasons only broadcast for UNKNOWN_APP, switch to ACTION_RECEIVED")
@ -71,11 +68,14 @@ class MeshService : Service(), Logging {
const val ACTION_MESH_CONNECTED = "$prefix.MESH_CONNECTED"
const val ACTION_MESSAGE_STATUS = "$prefix.MESSAGE_STATUS"
class IdNotFoundException(id: String) : Exception("ID not found $id")
class NodeNumNotFoundException(id: Int) : Exception("NodeNum not found $id")
open class NodeNotFoundException(reason: String) : Exception(reason)
class InvalidNodeIdException() : NodeNotFoundException("Invalid NodeId")
class NodeNumNotFoundException(id: Int) : NodeNotFoundException("NodeNum not found $id")
class IdNotFoundException(id: String) : NodeNotFoundException("ID not found $id")
/** We treat software update as similar to loss of comms to the regular bluetooth service (so things like sendPosition for background GPS ignores the problem */
class IsUpdatingException() : RadioNotConnectedException("Operation prohibited during firmware update")
class IsUpdatingException() :
RadioNotConnectedException("Operation prohibited during firmware update")
/**
* Talk to our running service and try to set a new device address. And then immediately
@ -244,7 +244,7 @@ class MeshService : Service(), Logging {
private fun sendToRadio(p: ToRadio.Builder) {
val b = p.build().toByteArray()
if(SoftwareUpdateService.isUpdating)
if (SoftwareUpdateService.isUpdating)
throw IsUpdatingException()
connectedRadio.sendToRadio(b)
@ -451,20 +451,37 @@ class MeshService : Service(), Logging {
n
)
/// Map a nodenum to the nodeid string, or return null if not present or no id found
private fun toNodeID(n: Int) =
if (n == NODENUM_BROADCAST) DataPacket.ID_BROADCAST else nodeDBbyNodeNum[n]?.user?.id
/** Map a nodenum to the nodeid string, or return null if not present
If we have a NodeInfo for this ID we prefer to return the string ID inside the user record.
but some nodes might not have a user record at all (because not yet received), in that case, we return
a hex version of the ID just based on the number */
private fun toNodeID(n: Int): String? =
if (n == DataPacket.NODENUM_BROADCAST)
DataPacket.ID_BROADCAST
else
nodeDBbyNodeNum[n]?.user?.id ?: DataPacket.nodeNumToDefaultId(n)
/// given a nodenum, return a db entry - creating if necessary
private fun getOrCreateNodeInfo(n: Int) =
nodeDBbyNodeNum.getOrPut(n) { -> NodeInfo(n) }
private val hexIdRegex = """\!([0-9A-Fa-f]+)""".toRegex()
/// Map a userid to a node/ node num, or throw an exception if not found
private fun toNodeInfo(id: String) =
nodeDBbyID[id]
?: throw IdNotFoundException(
id
)
/// We prefer to find nodes based on their assigned IDs, but if no ID has been assigned to a node, we can also find it based on node number
private fun toNodeInfo(id: String): NodeInfo {
// If this is a valid hexaddr will be !null
val hexStr = hexIdRegex.matchEntire(id)?.groups?.get(1)?.value
return nodeDBbyID[id] ?: when {
id == DataPacket.ID_LOCAL -> toNodeInfo(myNodeNum)
hexStr != null -> {
val n = hexStr.toLong(16).toInt()
nodeDBbyNodeNum[n] ?: throw IdNotFoundException(id)
}
else -> throw InvalidNodeIdException()
}
}
private val numNodes get() = nodeDBbyNodeNum.size
@ -473,12 +490,11 @@ class MeshService : Service(), Logging {
*/
private val numOnlineNodes get() = nodeDBbyNodeNum.values.count { it.isOnline }
private fun toNodeNum(id: String) =
when (id) {
DataPacket.ID_BROADCAST -> NODENUM_BROADCAST
DataPacket.ID_LOCAL -> myNodeNum
else -> toNodeInfo(id).num
}
private fun toNodeNum(id: String): Int = when (id) {
DataPacket.ID_BROADCAST -> DataPacket.NODENUM_BROADCAST
DataPacket.ID_LOCAL -> myNodeNum
else -> toNodeInfo(id).num
}
/// A helper function that makes it easy to update node info objects
private fun updateNodeInfo(nodeNum: Int, updatefn: (NodeInfo) -> Unit) {
@ -512,7 +528,7 @@ class MeshService : Service(), Logging {
from = myNodeNum
// We might need to change broadcast addresses to work with old device loads
to = if (useShortAddresses && idNum == NODENUM_BROADCAST) 255 else idNum
to = if (useShortAddresses && idNum == DataPacket.NODENUM_BROADCAST) 255 else idNum
}
/**
@ -598,7 +614,7 @@ 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.TEXT_MESSAGE_APP_VALUE) {
// discard old messages if needed then add the new one
while (recentDataPackets.size > 50)
recentDataPackets.removeAt(0)
@ -918,7 +934,11 @@ class MeshService : Service(), Logging {
// Do our startup init
try {
connectTimeMsec = System.currentTimeMillis()
SoftwareUpdateService.sendProgress(this, ProgressNotStarted, true) // Kinda crufty way of reiniting software update
SoftwareUpdateService.sendProgress(
this,
ProgressNotStarted,
true
) // Kinda crufty way of reiniting software update
startConfig()
} catch (ex: InvalidProtocolBufferException) {
@ -1143,7 +1163,6 @@ class MeshService : Service(), Logging {
}
/**
* If we are updating nodes we might need to use old (fixed by firmware build)
* region info to populate our new universal ROMs.
@ -1251,7 +1270,7 @@ class MeshService : Service(), Logging {
lat: Double,
lon: Double,
alt: Int,
destNum: Int = NODENUM_BROADCAST,
destNum: Int = DataPacket.NODENUM_BROADCAST,
wantResponse: Boolean = false
) {
debug("Sending our position to=$destNum lat=$lat, lon=$lon, alt=$alt")
@ -1268,7 +1287,8 @@ class MeshService : Service(), Logging {
val packet = newMeshPacketTo(destNum)
packet.decoded = MeshProtos.SubPacket.newBuilder().also {
val isNewPositionAPI = deviceVersion >= DeviceVersion("1.20.0") // We changed position APIs with this version
val isNewPositionAPI =
deviceVersion >= DeviceVersion("1.20.0") // We changed position APIs with this version
if (isNewPositionAPI) {
// Use the new position as data format
it.data = makeData(Portnums.PortNum.POSITION_APP_VALUE, position.toByteString())
@ -1290,13 +1310,12 @@ class MeshService : Service(), Logging {
lat: Double,
lon: Double,
alt: Int,
destNum: Int = NODENUM_BROADCAST,
destNum: Int = DataPacket.NODENUM_BROADCAST,
wantResponse: Boolean = false
) = serviceScope.handledLaunch {
try {
sendPosition(lat, lon, alt, destNum, wantResponse)
}
catch(ex: RadioNotConnectedException) {
} catch (ex: RadioNotConnectedException) {
warn("Ignoring disconnected radio during gps location update")
}
}

Wyświetl plik

@ -2,6 +2,7 @@ package com.geeksville.mesh.service
import android.location.Location
import android.os.RemoteException
import com.geeksville.mesh.DataPacket
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationResult
@ -37,7 +38,7 @@ class MeshServiceLocationCallback(
MeshService.info("got phone location")
if (location.isAccurateForMesh) { // if within 200 meters, or accuracy is unknown
val shouldSend = isAllowedToSend()
val destinationNumber = if (shouldSend) MeshService.NODENUM_BROADCAST else getNodeNum()
val destinationNumber = if (shouldSend) DataPacket.NODENUM_BROADCAST else getNodeNum()
sendPosition(location, destinationNumber, wantResponse = shouldSend)
} else {
MeshService.warn("accuracy ${location.accuracy} is too poor to use")

Wyświetl plik

@ -1,10 +1,7 @@
package com.geeksville.mesh.service
import com.geeksville.android.Logging
import com.geeksville.mesh.MeshProtos
import com.geeksville.mesh.Portnums
import com.geeksville.mesh.Position
import com.geeksville.mesh.R
import com.geeksville.mesh.*
import com.geeksville.mesh.model.getInitials
import com.google.protobuf.ByteString
import okhttp3.internal.toHexString
@ -89,7 +86,7 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi
nodeInfo = MeshProtos.NodeInfo.newBuilder().apply {
num = numIn
user = MeshProtos.User.newBuilder().apply {
id = "!0x" + num.toHexString()
id = DataPacket.nodeNumToDefaultId(numIn)
longName = "Sim " + num.toHexString()
shortName = getInitials(longName)
}.build()