sforkowany z mirror/meshtastic-android
distinguish between implicit and real ACKs (#552)
rodzic
1e95c200e6
commit
7c28c4091f
|
@ -30,6 +30,10 @@ class PacketRepository @Inject constructor(private val packetDaoLazy: dagger.Laz
|
|||
packetDao.updateMessageStatus(d, m)
|
||||
}
|
||||
|
||||
suspend fun getDataPacketById(requestId: Int) = withContext(Dispatchers.IO) {
|
||||
packetDao.getDataPacketById(requestId)
|
||||
}
|
||||
|
||||
suspend fun deleteAllMessages() = withContext(Dispatchers.IO) {
|
||||
packetDao.deleteAllMessages()
|
||||
}
|
||||
|
|
|
@ -47,4 +47,12 @@ interface PacketDao {
|
|||
val new = data.copy(status = m)
|
||||
findDataPacket(data)?.let { update(it.copy(data = new)) }
|
||||
}
|
||||
|
||||
@Query("Select data from packet")
|
||||
fun getDataPackets(): List<DataPacket>
|
||||
|
||||
@Transaction
|
||||
fun getDataPacketById(requestId: Int): DataPacket? {
|
||||
return getDataPackets().firstOrNull { it.id == requestId }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -660,10 +660,8 @@ class MeshService : Service(), Logging {
|
|||
shouldBroadcast =
|
||||
true // We always send acks to other apps, because they might care about the messages they sent
|
||||
val u = MeshProtos.Routing.parseFrom(data.payload)
|
||||
if (u.errorReasonValue == MeshProtos.Routing.Error.NONE_VALUE)
|
||||
handleAckNak(true, data.requestId)
|
||||
else
|
||||
handleAckNak(false, data.requestId)
|
||||
val isAck = u.errorReasonValue == MeshProtos.Routing.Error.NONE_VALUE
|
||||
handleAckNak(isAck, fromId, data.requestId)
|
||||
}
|
||||
|
||||
Portnums.PortNum.ADMIN_APP_VALUE -> {
|
||||
|
@ -778,9 +776,6 @@ class MeshService : Service(), Logging {
|
|||
/// If apps try to send packets when our radio is sleeping, we queue them here instead
|
||||
private val offlineSentPackets = mutableListOf<DataPacket>()
|
||||
|
||||
/** Keep a record of recently sent packets, so we can properly handle ack/nak */
|
||||
private val sentPackets = mutableMapOf<Int, DataPacket>()
|
||||
|
||||
/// Update our model and resend as needed for a MeshPacket we just received from the radio
|
||||
private fun handleReceivedMeshPacket(packet: MeshPacket) {
|
||||
if (haveNodeDB) {
|
||||
|
@ -824,6 +819,7 @@ class MeshService : Service(), Logging {
|
|||
* Change the status on a data packet and update watchers
|
||||
*/
|
||||
private fun changeStatus(p: DataPacket, m: MessageStatus) {
|
||||
if (p.status == m) return
|
||||
serviceScope.handledLaunch {
|
||||
packetRepository.get().updateMessageStatus(p, m)
|
||||
}
|
||||
|
@ -833,9 +829,17 @@ class MeshService : Service(), Logging {
|
|||
/**
|
||||
* Handle an ack/nak packet by updating sent message status
|
||||
*/
|
||||
private fun handleAckNak(isAck: Boolean, id: Int) {
|
||||
sentPackets.remove(id)?.let { p ->
|
||||
changeStatus(p, if (isAck) MessageStatus.DELIVERED else MessageStatus.ERROR)
|
||||
private fun handleAckNak(isAck: Boolean, fromId: String?, requestId: Int) {
|
||||
serviceScope.handledLaunch {
|
||||
val p = packetRepository.get().getDataPacketById(requestId)
|
||||
if (p != null && p.status != MessageStatus.RECEIVED) {
|
||||
val m = when {
|
||||
isAck && fromId == p.to -> MessageStatus.RECEIVED
|
||||
isAck -> MessageStatus.DELIVERED
|
||||
else -> MessageStatus.ERROR
|
||||
}
|
||||
changeStatus(p, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1546,28 +1550,6 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any sent packets that have been sitting around too long
|
||||
*
|
||||
* Note: we give each message what the timeout the device code is using, though in the normal
|
||||
* case the device will fail after 3 retries much sooner than that (and it will provide a nak to us)
|
||||
*/
|
||||
private fun deleteOldPackets() {
|
||||
myNodeInfo?.apply {
|
||||
val now = System.currentTimeMillis()
|
||||
|
||||
val old = sentPackets.values.filter { p ->
|
||||
(p.status == MessageStatus.ENROUTE && p.time + messageTimeoutMsec < now)
|
||||
}
|
||||
|
||||
// Do this using a separate list to prevent concurrent modification exceptions
|
||||
old.forEach { p ->
|
||||
handleAckNak(false, p.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun enqueueForSending(p: DataPacket) {
|
||||
p.status = MessageStatus.QUEUED
|
||||
offlineSentPackets.add(p)
|
||||
|
@ -1642,11 +1624,6 @@ class MeshService : Service(), Logging {
|
|||
// Keep a record of datapackets, so GUIs can show proper chat history
|
||||
rememberDataPacket(p)
|
||||
|
||||
if (p.id != 0) { // If we have an ID we can wait for an ack or nak
|
||||
deleteOldPackets()
|
||||
sentPackets[p.id] = p
|
||||
}
|
||||
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"data_send",
|
||||
DataPair("num_bytes", p.bytes.size),
|
||||
|
|
|
@ -167,6 +167,7 @@ class MessagesFragment : Fragment(), Logging {
|
|||
holder.messageTime.text = getShortDateTime(Date(msg.time))
|
||||
|
||||
val icon = when (msg.status) {
|
||||
MessageStatus.RECEIVED -> R.drawable.ic_twotone_how_to_reg_24
|
||||
MessageStatus.QUEUED -> R.drawable.ic_twotone_cloud_upload_24
|
||||
MessageStatus.DELIVERED -> R.drawable.cloud_on
|
||||
MessageStatus.ENROUTE -> R.drawable.ic_twotone_cloud_24
|
||||
|
@ -174,12 +175,18 @@ class MessagesFragment : Fragment(), Logging {
|
|||
else -> null
|
||||
}
|
||||
|
||||
if (icon != null) {
|
||||
if (icon != null && isLocal) {
|
||||
holder.messageStatusIcon.setImageResource(icon)
|
||||
holder.messageStatusIcon.visibility = View.VISIBLE
|
||||
} else
|
||||
holder.messageStatusIcon.visibility = View.GONE
|
||||
|
||||
holder.messageStatusIcon.setOnClickListener {
|
||||
if (isAdded) {
|
||||
Toast.makeText(context, "${msg.status}", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
holder.itemView.setOnLongClickListener {
|
||||
clickItem(holder)
|
||||
if (actionMode == null) {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillAlpha="0.3"
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11,8m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"
|
||||
android:strokeAlpha="0.3" />
|
||||
<path
|
||||
android:fillAlpha="0.3"
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M5,18h4.99L9,17l0.93,-0.94C7.55,16.33 5.2,17.37 5,18z"
|
||||
android:strokeAlpha="0.3" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM11,6c1.1,0 2,0.9 2,2s-0.9,2 -2,2 -2,-0.9 -2,-2 0.9,-2 2,-2zM10,18L5,18c0.2,-0.63 2.55,-1.67 4.93,-1.94h0.03l0.46,-0.45L12,14.06c-0.39,-0.04 -0.68,-0.06 -1,-0.06 -2.67,0 -8,1.34 -8,4v2h9l-2,-2zM20.6,12.5l-5.13,5.17 -2.07,-2.08L12,17l3.47,3.5L22,13.91z" />
|
||||
</vector>
|
Ładowanie…
Reference in New Issue