refactor: extract traceroute text from MeshService

This commit is contained in:
andrekir
2024-10-23 19:05:43 -03:00
parent eb80d419eb
commit 199b9a29d5
2 changed files with 64 additions and 48 deletions

View File

@@ -0,0 +1,60 @@
package com.geeksville.mesh.model
import com.geeksville.mesh.MeshProtos
import com.geeksville.mesh.MeshProtos.RouteDiscovery
import com.geeksville.mesh.Portnums
val MeshProtos.MeshPacket.fullRouteDiscovery: RouteDiscovery?
get() = with(decoded) {
if (hasDecoded() && !wantResponse && portnum == Portnums.PortNum.TRACEROUTE_APP) {
runCatching { RouteDiscovery.parseFrom(payload).toBuilder() }.getOrNull()?.apply {
clearRoute()
addAllRoute(listOf(to) + routeList + from)
if (hopStart > 0 && snrBackList.size > 0) { // otherwise back route is invalid
clearRouteBack()
addAllRouteBack(listOf(from) + routeBackList + to)
}
}?.build()
} else {
null
}
}
@Suppress("MagicNumber")
private fun formatTraceroutePath(nodesList: List<String>, snrList: List<Int>): String {
// nodesList should include both origin and destination nodes
// origin will not have an SNR value, but destination should
val snrStr = if (snrList.size == nodesList.size - 1) {
snrList
} else {
// use unknown SNR for entire route if snrList has invalid size
List(nodesList.size - 1) { -128 }
}.map { snr ->
val str = if (snr == -128) "?" else "${snr / 4}"
"$str dB"
}
return nodesList.map { userName ->
"$userName"
}.flatMapIndexed { i, nodeStr ->
if (i == 0) listOf(nodeStr) else listOf(snrStr[i - 1], nodeStr)
}.joinToString("\n")
}
private fun RouteDiscovery.getTracerouteResponse(
getUser: (nodeNum: Int) -> String,
): String = buildString {
if (routeList.isNotEmpty()) {
append("Route traced toward destination:\n\n")
append(formatTraceroutePath(routeList.map(getUser), snrTowardsList))
}
if (routeBackList.isNotEmpty()) {
append("\n\n")
append("Route traced back to us:\n\n")
append(formatTraceroutePath(routeBackList.map(getUser), snrBackList))
}
}
fun MeshProtos.MeshPacket.getTracerouteResponse(
getUser: (nodeNum: Int) -> String,
): String? = fullRouteDiscovery?.getTracerouteResponse(getUser)

View File

@@ -28,6 +28,7 @@ import com.geeksville.mesh.database.entity.NodeEntity
import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.database.entity.toNodeInfo
import com.geeksville.mesh.model.DeviceVersion
import com.geeksville.mesh.model.getTracerouteResponse
import com.geeksville.mesh.repository.datastore.RadioConfigRepository
import com.geeksville.mesh.repository.location.LocationRepository
import com.geeksville.mesh.repository.network.MQTTRepository
@@ -747,9 +748,9 @@ class MeshService : Service(), Logging {
}
Portnums.PortNum.TRACEROUTE_APP_VALUE -> {
if (data.wantResponse) return // ignore data from traceroute requests
val parsed = MeshProtos.RouteDiscovery.parseFrom(data.payload)
handleReceivedTraceroute(packet, parsed)
radioConfigRepository.setTracerouteResponse(
packet.getTracerouteResponse(::getUserName)
)
}
else -> debug("No custom processing needed for ${data.portnumValue}")
@@ -906,51 +907,6 @@ class MeshService : Service(), Logging {
}
}
@Suppress("MagicNumber")
private fun formatTraceroutePath(nodesList: List<Int>, snrList: List<Int>): String {
// nodesList should include both origin and destination nodes
// origin will not have an SNR value, but destination should
val snrStr = if (snrList.size == nodesList.size - 1) {
snrList
} else {
// use unknown SNR for entire route if snrList has invalid size
List(nodesList.size - 1) { -128 }
}.map { snr ->
val str = if (snr == -128) "?" else "${snr / 4}"
"$str dB"
}
return nodesList.map { nodeId ->
"${getUserName(nodeId)}"
}.flatMapIndexed { i, nodeStr ->
if (i == 0) listOf(nodeStr) else listOf(snrStr[i - 1], nodeStr)
}.joinToString("\n")
}
private fun handleReceivedTraceroute(packet: MeshPacket, trace: MeshProtos.RouteDiscovery) {
val nodesToward = mutableListOf<Int>()
nodesToward.add(packet.to)
nodesToward += trace.routeList
nodesToward.add(packet.from)
val nodesBack = mutableListOf<Int>()
if (packet.hopStart > 0 && trace.snrBackList.size > 0) { // otherwise back route is invalid
nodesBack.add(packet.from)
nodesBack += trace.routeBackList
nodesBack.add(packet.to)
}
radioConfigRepository.setTracerouteResponse(buildString {
append("Route traced toward destination:\n\n")
append(formatTraceroutePath(nodesToward, trace.snrTowardsList))
if (nodesBack.size > 0) {
append("\n\n")
append("Route traced back to us:\n\n")
append(formatTraceroutePath(nodesBack, trace.snrBackList))
}
})
}
// If apps try to send packets when our radio is sleeping, we queue them here instead
private val offlineSentPackets = mutableListOf<DataPacket>()