From 5e4470d25e09d0234eb14de6fd43c7dd22edbde3 Mon Sep 17 00:00:00 2001 From: Vadim Furman Date: Fri, 19 Mar 2021 14:33:55 -0700 Subject: [PATCH 1/6] Use default scope for file save and display snr --- .../java/com/geeksville/mesh/MainActivity.kt | 21 ++++++++++--------- .../main/java/com/geeksville/mesh/NodeInfo.kt | 3 ++- .../geeksville/mesh/service/MeshService.kt | 5 ++++- .../com/geeksville/mesh/ui/UsersFragment.kt | 9 +++++++- .../main/res/layout/adapter_node_layout.xml | 10 +++++++++ 5 files changed, 35 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index 2d2320950..49afe1710 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -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()) } } } diff --git a/app/src/main/java/com/geeksville/mesh/NodeInfo.kt b/app/src/main/java/com/geeksville/mesh/NodeInfo.kt index 77d26af77..2daeaeabd 100644 --- a/app/src/main/java/com/geeksville/mesh/NodeInfo.kt +++ b/app/src/main/java/com/geeksville/mesh/NodeInfo.kt @@ -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 diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt index 236c352e9..76fd3ca61 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -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) diff --git a/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt index 0b6529679..db90c63f8 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt @@ -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() { @@ -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() diff --git a/app/src/main/res/layout/adapter_node_layout.xml b/app/src/main/res/layout/adapter_node_layout.xml index 86d70f043..610eb0d60 100644 --- a/app/src/main/res/layout/adapter_node_layout.xml +++ b/app/src/main/res/layout/adapter_node_layout.xml @@ -71,6 +71,16 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/batteryIcon" /> + + Date: Sun, 21 Mar 2021 18:15:54 -0700 Subject: [PATCH 2/6] Fixed formatting --- app/src/main/java/com/geeksville/mesh/MainActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index 94c12b7cf..08925b0f0 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -1102,7 +1102,7 @@ class MainActivity : AppCompatActivity(), Logging, } else if (my_position != null) { val dist: Int = positionToMeter(my_position!!, position).roundToInt() - fs.write("%x,%f,%d,%d".format( packet_proto.from, + fs.write("%x,%f,%d,%d\n".format( packet_proto.from, packet_proto.rxSnr, packet_proto.rxTime, dist).toByteArray()) } } From 6e545e628b2db6ea682a473b0b9711a9e79b3b71 Mon Sep 17 00:00:00 2001 From: Daniel Nemenyi Date: Mon, 22 Mar 2021 09:14:29 +0000 Subject: [PATCH 3/6] Fix expired link The 'Firmware update required' modal contains an expired link to the Wiki. This commit points the user towards the Firmware Installation section on Github instead. * app/src/main/res/values/strings.xml --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 11f071ffd..346dfd579 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -90,7 +90,7 @@ Protocol stress test Advanced settings Firmware update required - The radio firmware is too old to talk to this application, please go to the settings pane and choose "Update Firmware". For more information on this see our wiki. + The radio firmware is too old to talk to this application, please go to the settings pane and choose "Update Firmware". For more information on this see our Firmware Installation guide on Github. Okay You must set a region! Region From 0d9f31f7fbacd2987399383653e7519400058f58 Mon Sep 17 00:00:00 2001 From: Vadim Furman Date: Mon, 22 Mar 2021 21:10:58 -0700 Subject: [PATCH 4/6] Pipe rssi to the view --- .../main/java/com/geeksville/mesh/NodeInfo.kt | 3 ++- .../geeksville/mesh/service/MeshService.kt | 1 + .../com/geeksville/mesh/ui/UsersFragment.kt | 15 ++++++++--- .../main/res/layout/adapter_node_layout.xml | 26 ++++++++++--------- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/NodeInfo.kt b/app/src/main/java/com/geeksville/mesh/NodeInfo.kt index 86d32d78a..f4864dd91 100644 --- a/app/src/main/java/com/geeksville/mesh/NodeInfo.kt +++ b/app/src/main/java/com/geeksville/mesh/NodeInfo.kt @@ -83,7 +83,8 @@ data class NodeInfo( val num: Int, // This is immutable, and used as a key var user: MeshUser? = null, var position: Position? = null, - var snr: Float = 1000.0f + var snr: Float = Float.MAX_VALUE, + var rssi: Int = Int.MAX_VALUE ) : Parcelable { /// Return the last time we've seen this node in secs since 1970 diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt index e0f38200f..68e9e1652 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -926,6 +926,7 @@ class MeshService : Service(), Logging { // 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 + it.rssi = packet.rxRssi } handleReceivedData(packet) diff --git a/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt index 744a87106..0649aa429 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/UsersFragment.kt @@ -21,6 +21,7 @@ import com.geeksville.mesh.databinding.NodelistFragmentBinding import com.geeksville.mesh.model.UIViewModel import com.geeksville.util.formatAgo import java.net.URLEncoder +import kotlin.math.roundToInt class UsersFragment : ScreenFragment("Users"), Logging { @@ -41,7 +42,7 @@ class UsersFragment : ScreenFragment("Users"), Logging { val batteryPctView = itemView.batteryPercentageView val lastTime = itemView.lastConnectionView val powerIcon = itemView.batteryIcon - val snrView = itemView.snrView + val signalView = itemView.signalView } private val nodesAdapter = object : RecyclerView.Adapter() { @@ -143,10 +144,16 @@ class UsersFragment : ScreenFragment("Users"), Logging { holder.lastTime.text = formatAgo(n.lastSeen); if ((n.num == ourNodeInfo?.num) || (n.snr > 100f)) { - holder.snrView.visibility = View.INVISIBLE + holder.signalView.visibility = View.INVISIBLE } else { - holder.snrView.visibility = View.VISIBLE - holder.snrView.text = n.snr.toString() + val text = if (n.rssi < 0) { + "rssi:${n.rssi} snr:${n.snr.roundToInt()}" + } else { + // Older devices do not send rssi. Remove this branch once upgraded past 1.2.1 + "snr:${n.snr.roundToInt()}" + } + holder.signalView.text = text + holder.signalView.visibility = View.VISIBLE } } diff --git a/app/src/main/res/layout/adapter_node_layout.xml b/app/src/main/res/layout/adapter_node_layout.xml index 75905d5e9..b30bc1394 100644 --- a/app/src/main/res/layout/adapter_node_layout.xml +++ b/app/src/main/res/layout/adapter_node_layout.xml @@ -60,7 +60,7 @@ android:layout_marginBottom="8dp" android:text="@string/sample_coords" android:textAppearance="@style/TextAppearance.AppCompat.Small" - app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toEndOf="@+id/distance_view" app:layout_constraintTop_toBottomOf="@+id/imageView" app:layout_constraintVertical_bias="0.0" /> @@ -85,16 +85,6 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/batteryIcon" /> - - @@ -116,6 +107,17 @@ app:layout_constraintBottom_toBottomOf="@+id/lastCommIcon" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/lastCommIcon" /> + + + \ No newline at end of file From 13d63ee52b99d1f5433b67a83671020606fe5e7e Mon Sep 17 00:00:00 2001 From: Vadim Furman Date: Mon, 22 Mar 2021 21:21:58 -0700 Subject: [PATCH 5/6] More rssi --- app/src/main/java/com/geeksville/mesh/MainActivity.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index 08925b0f0..c7879cf1d 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -1090,7 +1090,7 @@ class MainActivity : AppCompatActivity(), Logging, applicationContext.contentResolver.openFileDescriptor(file_uri, "w")?.use { FileOutputStream(it.fileDescriptor).use { fs -> // Write header - fs.write(("from,snr,time,dist\n").toByteArray()); + fs.write(("from,rssi,snr,time,dist\n").toByteArray()); // Packets are ordered by time, we keep most recent position of // our device in my_position. var my_position: MeshProtos.Position? = null @@ -1100,9 +1100,8 @@ class MainActivity : AppCompatActivity(), Logging, if (packet_proto.from == myNodeNum) { my_position = position } else if (my_position != null) { - val dist: Int = - positionToMeter(my_position!!, position).roundToInt() - fs.write("%x,%f,%d,%d\n".format( packet_proto.from, + val dist = positionToMeter(my_position!!, position).roundToInt() + fs.write("%x,%d,%f,%d,%d\n".format(packet_proto.from,packet_proto.rxRssi, packet_proto.rxSnr, packet_proto.rxTime, dist).toByteArray()) } } From 691c5862cbe302f98b2eb74e864fd5b25fff32e8 Mon Sep 17 00:00:00 2001 From: Vadim Furman Date: Mon, 22 Mar 2021 21:32:40 -0700 Subject: [PATCH 6/6] Updated proto --- app/src/main/proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/proto b/app/src/main/proto index ac26ffdc7..820fa497d 160000 --- a/app/src/main/proto +++ b/app/src/main/proto @@ -1 +1 @@ -Subproject commit ac26ffdc71dad5765124186df5ec38771a0e5240 +Subproject commit 820fa497dfde07e129cad6955bf2f4b2b9cecebc