From 10ad07e136eee3b592456937e7f87efdcf5e18f1 Mon Sep 17 00:00:00 2001 From: geeksville Date: Mon, 10 Feb 2020 15:31:56 -0800 Subject: [PATCH] we now fetch any new rxmessages when they arrive at the radio --- app/src/main/AndroidManifest.xml | 8 +-- .../java/com/geeksville/mesh/MainActivity.kt | 12 +++- .../{ => service}/BootCompleteReceiver.kt | 2 +- .../mesh/{ => service}/Constants.kt | 2 +- .../mesh/{ => service}/MeshService.kt | 64 ++++++++++++++----- .../{ => service}/RadioInterfaceService.kt | 14 ++-- .../mesh/{ => service}/SafeBluetooth.kt | 13 ++-- .../mesh/{ => service}/SimRadio.disabled | 0 .../{ => service}/SoftwareUpdateService.kt | 12 +++- .../com/geeksville/mesh/ui/NodeInfoCard.kt | 2 +- .../java/com/geeksville/mesh/ui/Status.kt | 24 +++++-- 11 files changed, 110 insertions(+), 43 deletions(-) rename app/src/main/java/com/geeksville/mesh/{ => service}/BootCompleteReceiver.kt (91%) rename app/src/main/java/com/geeksville/mesh/{ => service}/Constants.kt (90%) rename app/src/main/java/com/geeksville/mesh/{ => service}/MeshService.kt (90%) rename app/src/main/java/com/geeksville/mesh/{ => service}/RadioInterfaceService.kt (97%) rename app/src/main/java/com/geeksville/mesh/{ => service}/SafeBluetooth.kt (98%) rename app/src/main/java/com/geeksville/mesh/{ => service}/SimRadio.disabled (100%) rename app/src/main/java/com/geeksville/mesh/{ => service}/SoftwareUpdateService.kt (96%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5d18986f..fad7bd1b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -53,14 +53,14 @@ @@ -70,7 +70,7 @@ @@ -85,7 +85,7 @@ - + diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index 7bcd10ca..7bded448 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -17,6 +17,7 @@ import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.ui.core.setContent import com.geeksville.android.Logging +import com.geeksville.mesh.service.* import com.geeksville.mesh.ui.MeshApp import com.geeksville.mesh.ui.TextMessage import com.geeksville.mesh.ui.UIState @@ -175,7 +176,7 @@ class MainActivity : AppCompatActivity(), Logging { else -> TODO() } } - RadioInterfaceService.CONNECTCHANGED_ACTION -> { + MeshService.ACTION_MESH_CONNECTED -> { UIState.isConnected.value = intent.getBooleanExtra(EXTRA_CONNECTED, false) debug("connchange ${UIState.isConnected.value}") } @@ -200,7 +201,12 @@ class MainActivity : AppCompatActivity(), Logging { // make some placeholder nodeinfos UIState.nodes.value = - m.online.toList().map { it to NodeInfo(0, MeshUser(it, "unknown", "unk")) }.toMap() + m.online.toList().map { + it to NodeInfo( + 0, + MeshUser(it, "unknown", "unk") + ) + }.toMap() } override fun onServiceDisconnected(name: ComponentName) { @@ -218,7 +224,7 @@ class MainActivity : AppCompatActivity(), Logging { //val intent = Intent(this, MeshService::class.java) //intent.action = IMeshService::class.java.name val intent = Intent() - intent.setClassName("com.geeksville.mesh", "com.geeksville.mesh.MeshService") + intent.setClassName("com.geeksville.mesh", "com.geeksville.mesh.service.MeshService") // Before binding we want to explicitly create - so the service stays alive forever (so it can keep // listening for the bluetooth packets arriving from the radio. And when they arrive forward them diff --git a/app/src/main/java/com/geeksville/mesh/BootCompleteReceiver.kt b/app/src/main/java/com/geeksville/mesh/service/BootCompleteReceiver.kt similarity index 91% rename from app/src/main/java/com/geeksville/mesh/BootCompleteReceiver.kt rename to app/src/main/java/com/geeksville/mesh/service/BootCompleteReceiver.kt index 3c88575c..7541c857 100644 --- a/app/src/main/java/com/geeksville/mesh/BootCompleteReceiver.kt +++ b/app/src/main/java/com/geeksville/mesh/service/BootCompleteReceiver.kt @@ -1,4 +1,4 @@ -package com.geeksville.mesh +package com.geeksville.mesh.service import android.content.BroadcastReceiver import android.content.Context diff --git a/app/src/main/java/com/geeksville/mesh/Constants.kt b/app/src/main/java/com/geeksville/mesh/service/Constants.kt similarity index 90% rename from app/src/main/java/com/geeksville/mesh/Constants.kt rename to app/src/main/java/com/geeksville/mesh/service/Constants.kt index 36f67984..e5c74a53 100644 --- a/app/src/main/java/com/geeksville/mesh/Constants.kt +++ b/app/src/main/java/com/geeksville/mesh/service/Constants.kt @@ -1,4 +1,4 @@ -package com.geeksville.mesh +package com.geeksville.mesh.service const val prefix = "com.geeksville.mesh" diff --git a/app/src/main/java/com/geeksville/mesh/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt similarity index 90% rename from app/src/main/java/com/geeksville/mesh/MeshService.kt rename to app/src/main/java/com/geeksville/mesh/service/MeshService.kt index 85eb1813..87a6701b 100644 --- a/app/src/main/java/com/geeksville/mesh/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -1,4 +1,4 @@ -package com.geeksville.mesh +package com.geeksville.mesh.service import android.app.Notification import android.app.NotificationChannel @@ -13,6 +13,9 @@ import androidx.annotation.RequiresApi import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat.PRIORITY_MIN import com.geeksville.android.Logging +import com.geeksville.mesh.IMeshService +import com.geeksville.mesh.IRadioInterfaceService +import com.geeksville.mesh.MeshProtos import com.geeksville.mesh.MeshProtos.MeshPacket import com.geeksville.mesh.MeshProtos.ToRadio import com.geeksville.util.exceptionReporter @@ -55,6 +58,7 @@ class MeshService : Service(), Logging { /// Intents broadcast by MeshService const val ACTION_RECEIVED_DATA = "$prefix.RECEIVED_DATA" const val ACTION_NODE_CHANGE = "$prefix.NODE_CHANGE" + const val ACTION_MESH_CONNECTED = "$prefix.MESH_CONNECTED" class IdNotFoundException(id: String) : Exception("ID not found $id") class NodeNumNotFoundException(id: Int) : Exception("NodeNum not found $id") @@ -78,7 +82,9 @@ class MeshService : Service(), Logging { see com.geeksville.mesh broadcast intents // RECEIVED_OPAQUE for data received from other nodes // NODE_CHANGE for new IDs appearing or disappearing - // CONNECTION_CHANGED for losing/gaining connection to the packet radio + // ACTION_MESH_CONNECTED for losing/gaining connection to the packet radio (note, this is not + the same as RadioInterfaceService.RADIO_CONNECTED_ACTION, because it implies we have assembled a valid + node db. */ private fun explicitBroadcast(intent: Intent) { @@ -89,6 +95,7 @@ class MeshService : Service(), Logging { } } + /** * The RECEIVED_OPAQUE: * Payload will be the raw bytes which were contained within a MeshPacket.Opaque field @@ -134,7 +141,9 @@ class MeshService : Service(), Logging { private val radioConnection = object : ServiceConnection { override fun onServiceConnected(name: ComponentName?, service: IBinder?) { - val m = IRadioInterfaceService.Stub.asInterface(service) + val m = IRadioInterfaceService.Stub.asInterface( + service + ) radioService = m } @@ -210,7 +219,7 @@ class MeshService : Service(), Logging { // we listen for messages from the radio receiver _before_ trying to create the service val filter = IntentFilter() filter.addAction(RadioInterfaceService.RECEIVE_FROMRADIO_ACTION) - filter.addAction(RadioInterfaceService.CONNECTCHANGED_ACTION) + filter.addAction(RadioInterfaceService.RADIO_CONNECTED_ACTION) registerReceiver(radioInterfaceReceiver, filter) // We in turn need to use the radiointerface service @@ -239,7 +248,8 @@ class MeshService : Service(), Logging { private var isConnected = false /// We learn this from the node db sent by the device - it is stable for the entire session - private var ourNodeNum = NODE_NUM_UNKNOWN + private var ourNodeNum = + NODE_NUM_UNKNOWN // The database of active nodes, index is the node number private val nodeDBbyNodeNum = mutableMapOf() @@ -255,7 +265,9 @@ class MeshService : Service(), Logging { /// /// Map a nodenum to a node, or throw an exception if not found - private fun toNodeInfo(n: Int) = nodeDBbyNodeNum[n] ?: throw NodeNumNotFoundException(n) + private fun toNodeInfo(n: Int) = nodeDBbyNodeNum[n] ?: throw NodeNumNotFoundException( + n + ) /// Map a nodenum to the nodeid string, or throw an exception if not present private fun toNodeID(n: Int) = toNodeInfo(n).user?.id @@ -267,7 +279,9 @@ class MeshService : Service(), Logging { /// 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) + ?: throw IdNotFoundException( + id + ) // ?: getOrCreateNodeInfo(10) // FIXME hack for now - throw IdNotFoundException(id) @@ -354,7 +368,11 @@ class MeshService : Service(), Logging { /// Update our DB of users based on someone sending out a User subpacket private fun handleReceivedUser(fromNum: Int, p: MeshProtos.User) { updateNodeInfo(fromNum) { - it.user = MeshUser(p.id, p.longName, p.shortName) + it.user = MeshUser( + p.id, + p.longName, + p.shortName + ) } } @@ -405,7 +423,9 @@ class MeshService : Service(), Logging { //val sim = SimRadio(this@MeshService) //sim.start() // Fake up our node id info and some past packets from other nodes - val myInfo = MeshProtos.MyNodeInfo.parseFrom(connectedRadio.readMyNode()) + val myInfo = MeshProtos.MyNodeInfo.parseFrom( + connectedRadio.readMyNode() + ) ourNodeNum = myInfo.myNodeNum // Ask for the current node DB @@ -414,14 +434,19 @@ class MeshService : Service(), Logging { // read all the infos until we get back null var infoBytes = connectedRadio.readNodeInfo() while (infoBytes != null) { - val info = MeshProtos.NodeInfo.parseFrom(infoBytes) + val info = + MeshProtos.NodeInfo.parseFrom(infoBytes) debug("Received initial nodeinfo $info") // Just replace/add any entry updateNodeInfo(info.num) { if (info.hasUser()) it.user = - MeshUser(info.user.id, info.user.longName, info.user.shortName) + MeshUser( + info.user.id, + info.user.longName, + info.user.shortName + ) if (info.hasPosition()) it.position = Position( @@ -450,14 +475,22 @@ class MeshService : Service(), Logging { debug("Received broadcast ${intent.action}") when (intent.action) { - RadioInterfaceService.CONNECTCHANGED_ACTION -> { + RadioInterfaceService.RADIO_CONNECTED_ACTION -> { onConnectionChanged(intent.getBooleanExtra(EXTRA_CONNECTED, false)) - explicitBroadcast(intent) // forward the connection change message to anyone who is listening to us + + // forward the connection change message to anyone who is listening to us. but change the action + // to prevent an infinite loop from us receiving our own broadcast. ;-) + intent.action = ACTION_MESH_CONNECTED + explicitBroadcast(intent) } RadioInterfaceService.RECEIVE_FROMRADIO_ACTION -> { val proto = - MeshProtos.FromRadio.parseFrom(intent.getByteArrayExtra(EXTRA_PAYLOAD)!!) + MeshProtos.FromRadio.parseFrom( + intent.getByteArrayExtra( + EXTRA_PAYLOAD + )!! + ) info("Received from radio service: ${proto.toOneLineString()}") when (proto.variantCase.number) { MeshProtos.FromRadio.PACKET_FIELD_NUMBER -> handleReceivedMeshPacket( @@ -507,7 +540,8 @@ class MeshService : Service(), Logging { // encapsulate our payload in the proper protobufs and fire it off val packet = buildMeshPacket(destId) { data = MeshProtos.Data.newBuilder().also { - it.typ = MeshProtos.Data.Type.SIGNAL_OPAQUE + it.typ = + MeshProtos.Data.Type.SIGNAL_OPAQUE it.payload = ByteString.copyFrom(payloadIn) }.build() } diff --git a/app/src/main/java/com/geeksville/mesh/RadioInterfaceService.kt b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/RadioInterfaceService.kt rename to app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt index 2bdfe5fa..4c50ec2b 100644 --- a/app/src/main/java/com/geeksville/mesh/RadioInterfaceService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt @@ -1,4 +1,4 @@ -package com.geeksville.mesh +package com.geeksville.mesh.service import android.app.Service import android.bluetooth.BluetoothAdapter @@ -10,6 +10,7 @@ import android.os.IBinder import com.geeksville.android.BinaryLogFile import com.geeksville.android.Logging import com.geeksville.concurrent.DeferredExecution +import com.geeksville.mesh.IRadioInterfaceService import com.geeksville.util.toRemoteExceptions import java.util.* @@ -91,9 +92,9 @@ class RadioInterfaceService : Service(), Logging { const val RECEIVE_FROMRADIO_ACTION = "$prefix.RECEIVE_FROMRADIO" /** - * This is broadcast when connection state changed (it is also rebroadcast by the MeshService) + * This is broadcast when connection state changed */ - const val CONNECTCHANGED_ACTION = "$prefix.CONNECT_CHANGED" + const val RADIO_CONNECTED_ACTION = "$prefix.CONNECT_CHANGED" private val BTM_SERVICE_UUID = UUID.fromString("6ba1b218-15a8-461f-9fa8-5dcae273eafd") private val BTM_FROMRADIO_CHARACTER = @@ -150,7 +151,7 @@ class RadioInterfaceService : Service(), Logging { private fun broadcastConnectionChanged(isConnected: Boolean) { debug("Broadcasting connection=$isConnected") - val intent = Intent(CONNECTCHANGED_ACTION) + val intent = Intent(RADIO_CONNECTED_ACTION) intent.putExtra(EXTRA_CONNECTED, isConnected) sendBroadcast(intent) } @@ -171,7 +172,10 @@ class RadioInterfaceService : Service(), Logging { // Handle an incoming packet from the radio, broadcasts it as an android intent private fun handleFromRadio(p: ByteArray) { - broadcastReceivedFromRadio(this, p) + broadcastReceivedFromRadio( + this, + p + ) } /// Attempt to read from the fromRadio mailbox, if data is found broadcast it to android apps diff --git a/app/src/main/java/com/geeksville/mesh/SafeBluetooth.kt b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/SafeBluetooth.kt rename to app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt index 0553ec74..b49fca13 100644 --- a/app/src/main/java/com/geeksville/mesh/SafeBluetooth.kt +++ b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt @@ -1,4 +1,4 @@ -package com.geeksville.mesh +package com.geeksville.mesh.service import android.bluetooth.* import android.content.BroadcastReceiver @@ -244,7 +244,12 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD } private fun queueWork(tag: String, cont: Continuation, initFn: () -> Boolean) { - val btCont = BluetoothContinuation(tag, cont, initFn) + val btCont = + BluetoothContinuation( + tag, + cont, + initFn + ) synchronized(workQueue) { debug("Enqueuing work: ${btCont.tag}") @@ -341,7 +346,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD private fun queueReadCharacteristic( c: BluetoothGattCharacteristic, cont: Continuation - ) = queueWork("readc", cont) { gatt!!.readCharacteristic(c) } + ) = queueWork("readC ${c.uuid}", cont) { gatt!!.readCharacteristic(c) } fun asyncReadCharacteristic( c: BluetoothGattCharacteristic, @@ -383,7 +388,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD private fun queueWriteCharacteristic( c: BluetoothGattCharacteristic, cont: Continuation - ) = queueWork("writeC", cont) { gatt!!.writeCharacteristic(c) } + ) = queueWork("writeC ${c.uuid}", cont) { gatt!!.writeCharacteristic(c) } fun asyncWriteCharacteristic( c: BluetoothGattCharacteristic, diff --git a/app/src/main/java/com/geeksville/mesh/SimRadio.disabled b/app/src/main/java/com/geeksville/mesh/service/SimRadio.disabled similarity index 100% rename from app/src/main/java/com/geeksville/mesh/SimRadio.disabled rename to app/src/main/java/com/geeksville/mesh/service/SimRadio.disabled diff --git a/app/src/main/java/com/geeksville/mesh/SoftwareUpdateService.kt b/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt similarity index 96% rename from app/src/main/java/com/geeksville/mesh/SoftwareUpdateService.kt rename to app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt index 56b00a76..1aa3f58c 100644 --- a/app/src/main/java/com/geeksville/mesh/SoftwareUpdateService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt @@ -1,4 +1,4 @@ -package com.geeksville.mesh +package com.geeksville.mesh.service import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothDevice @@ -13,6 +13,7 @@ import android.content.Intent import android.os.ParcelUuid import androidx.core.app.JobIntentService import com.geeksville.android.Logging +import com.geeksville.mesh.MainActivity import java.util.* import java.util.zip.CRC32 @@ -40,7 +41,11 @@ class SoftwareUpdateService : JobIntentService(), Logging { fun startUpdate() { info("starting update") - val sync = SafeBluetooth(this@SoftwareUpdateService, device) + val sync = + SafeBluetooth( + this@SoftwareUpdateService, + device + ) val firmwareStream = assets.open("firmware.bin") val firmwareCrc = CRC32() @@ -216,7 +221,8 @@ class SoftwareUpdateService : JobIntentService(), Logging { fun enqueueWork(context: Context, work: Intent) { enqueueWork( context, - SoftwareUpdateService::class.java, JOB_ID, work + SoftwareUpdateService::class.java, + JOB_ID, work ) } } diff --git a/app/src/main/java/com/geeksville/mesh/ui/NodeInfoCard.kt b/app/src/main/java/com/geeksville/mesh/ui/NodeInfoCard.kt index b5f32dad..3d19a335 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/NodeInfoCard.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/NodeInfoCard.kt @@ -9,8 +9,8 @@ import androidx.ui.material.MaterialTheme import androidx.ui.material.ProvideEmphasis import androidx.ui.tooling.preview.Preview import androidx.ui.unit.dp -import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.R +import com.geeksville.mesh.service.NodeInfo @Composable diff --git a/app/src/main/java/com/geeksville/mesh/ui/Status.kt b/app/src/main/java/com/geeksville/mesh/ui/Status.kt index c05ad3ca..66d4b8d1 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Status.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Status.kt @@ -2,9 +2,9 @@ package com.geeksville.mesh.ui import androidx.compose.Model import androidx.compose.mutableStateOf -import com.geeksville.mesh.MeshUser -import com.geeksville.mesh.NodeInfo -import com.geeksville.mesh.Position +import com.geeksville.mesh.service.MeshUser +import com.geeksville.mesh.service.NodeInfo +import com.geeksville.mesh.service.Position import java.util.* // defines the screens we have in the app @@ -26,12 +26,20 @@ object UIState { private val testPositions = arrayOf( Position(32.776665, -96.796989, 35), // dallas Position(32.960758, -96.733521, 35), // richardson - Position(32.912901, -96.781776, 35) // north dallas + Position( + 32.912901, + -96.781776, + 35 + ) // north dallas ) val testNodeNoPosition = NodeInfo( 8, - MeshUser("+6508765308".format(8), "Kevin MesterNoLoc", "KLO"), + MeshUser( + "+6508765308".format(8), + "Kevin MesterNoLoc", + "KLO" + ), null, 12345 ) @@ -39,7 +47,11 @@ object UIState { val testNodes = testPositions.mapIndexed { index, it -> NodeInfo( 9 + index, - MeshUser("+65087653%02d".format(9 + index), "Kevin Mester$index", "KM$index"), + MeshUser( + "+65087653%02d".format(9 + index), + "Kevin Mester$index", + "KM$index" + ), it, 12345 )