diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5d18986f2..fad7bd1b3 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 7bcd10ca5..7bded4481 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 3c88575c1..7541c857b 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 36f67984f..e5c74a535 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 85eb18132..87a6701bd 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 2bdfe5fa7..4c50ec2b5 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 0553ec742..b49fca13a 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 56b00a765..1aa3f58c6 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 b5f32dad3..3d19a3356 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 c05ad3ca3..66d4b8d12 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
)