kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
Use default scope for file save and display snr
rodzic
78a08898fe
commit
5e4470d25e
|
@ -60,11 +60,9 @@ import com.google.android.material.tabs.TabLayoutMediator
|
|||
import com.google.protobuf.InvalidProtocolBufferException
|
||||
import com.vorlonsoft.android.rate.AppRate
|
||||
import com.vorlonsoft.android.rate.StoreType
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.FileOutputStream
|
||||
import java.lang.Runnable
|
||||
import java.nio.charset.Charset
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
@ -559,10 +557,16 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
CREATE_CSV_FILE -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
data?.data?.let { file_uri ->
|
||||
// model.allPackets is a result of a query, so we need to use observer for
|
||||
// the query to materialize
|
||||
model.allPackets.observe(this, { packets ->
|
||||
if (packets != null) {
|
||||
saveMessagesCSV(file_uri, packets)
|
||||
// no need for observer once got non-null list
|
||||
model.allPackets.removeObservers(this)
|
||||
// execute on the default thread pool to not block the main thread
|
||||
CoroutineScope(Dispatchers.Default + Job()).handledLaunch {
|
||||
saveMessagesCSV(file_uri, packets)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1084,11 +1088,8 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
} else if (my_position != null) {
|
||||
val dist: Int =
|
||||
positionToMeter(my_position!!, position).roundToInt()
|
||||
fs.write(
|
||||
("${packet_proto.from.toUInt().toString(16)}," +
|
||||
"${packet_proto.rxSnr},${packet_proto.rxTime},$dist\n")
|
||||
.toByteArray()
|
||||
)
|
||||
fs.write("%x,%f,%d,%d".format( packet_proto.from,
|
||||
packet_proto.rxSnr, packet_proto.rxTime, dist).toByteArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,8 @@ data class Position(
|
|||
data class NodeInfo(
|
||||
val num: Int, // This is immutable, and used as a key
|
||||
var user: MeshUser? = null,
|
||||
var position: Position? = null
|
||||
var position: Position? = null,
|
||||
var snr: Float = 1000.0f
|
||||
) : Parcelable {
|
||||
|
||||
/// Return the last time we've seen this node in secs since 1970
|
||||
|
|
|
@ -167,7 +167,7 @@ class MeshService : Service(), Logging {
|
|||
// FIXME - currently we don't support location reading without google play
|
||||
if (fusedLocationClient == null && isGooglePlayAvailable(this)) {
|
||||
GeeksvilleApplication.analytics.track("location_start") // Figure out how many users needed to use the phone GPS
|
||||
|
||||
|
||||
val request = LocationRequest.create().apply {
|
||||
interval = requestInterval
|
||||
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
|
||||
|
@ -713,6 +713,7 @@ class MeshService : Service(), Logging {
|
|||
// Handle new style position info
|
||||
Portnums.PortNum.POSITION_APP_VALUE -> {
|
||||
val u = MeshProtos.Position.parseFrom(data.payload)
|
||||
debug("position_app ${packet.from} ${u.toOneLineString()}")
|
||||
handleReceivedPosition(packet.from, u, dataPacket.time)
|
||||
}
|
||||
|
||||
|
@ -820,6 +821,7 @@ class MeshService : Service(), Logging {
|
|||
defaultTime: Long = System.currentTimeMillis()
|
||||
) {
|
||||
updateNodeInfo(fromNum) {
|
||||
debug("update ${it.user?.longName} with ${p.toOneLineString()}")
|
||||
it.position = Position(p)
|
||||
updateNodeInfoTime(it, (defaultTime / 1000).toInt())
|
||||
}
|
||||
|
@ -916,6 +918,7 @@ class MeshService : Service(), Logging {
|
|||
updateNodeInfo(fromNum) {
|
||||
// Update our last seen based on any valid timestamps. If the device didn't provide a timestamp make one
|
||||
updateNodeInfoTime(it, rxTime)
|
||||
it.snr = packet.rxSnr
|
||||
}
|
||||
|
||||
handleReceivedData(packet)
|
||||
|
|
|
@ -37,6 +37,7 @@ class UsersFragment : ScreenFragment("Users"), Logging {
|
|||
val batteryPctView = itemView.batteryPercentageView
|
||||
val lastTime = itemView.lastConnectionView
|
||||
val powerIcon = itemView.batteryIcon
|
||||
val snrView = itemView.snrView
|
||||
}
|
||||
|
||||
private val nodesAdapter = object : RecyclerView.Adapter<ViewHolder>() {
|
||||
|
@ -115,10 +116,16 @@ class UsersFragment : ScreenFragment("Users"), Logging {
|
|||
} else {
|
||||
holder.distanceView.visibility = View.INVISIBLE
|
||||
}
|
||||
|
||||
debug("node=${n.user?.longName} bat=${n.batteryPctLevel}")
|
||||
renderBattery(n.batteryPctLevel, holder)
|
||||
|
||||
holder.lastTime.text = getLastTimeValue(n)
|
||||
if ((n.num == ourNodeInfo?.num) || (n.snr > 100f)) {
|
||||
holder.snrView.visibility = View.INVISIBLE
|
||||
} else {
|
||||
holder.snrView.visibility = View.VISIBLE
|
||||
holder.snrView.text = n.snr.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private var nodes = arrayOf<NodeInfo>()
|
||||
|
|
|
@ -71,6 +71,16 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/batteryIcon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/snrView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="-8.0"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/lastCommIcon" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/lastCommIcon"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
Ładowanie…
Reference in New Issue