we now fetch any new rxmessages when they arrive at the radio

pull/8/head
geeksville 2020-02-10 15:31:56 -08:00
rodzic 6244556f8b
commit 10ad07e136
11 zmienionych plików z 110 dodań i 43 usunięć

Wyświetl plik

@ -53,14 +53,14 @@
<!-- we need bind job service for oreo -->
<service
android:name="com.geeksville.mesh.SoftwareUpdateService"
android:name="com.geeksville.mesh.service.SoftwareUpdateService"
android:enabled="true"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"></service>
<!-- This is the public API for doing mesh radio operations from android apps -->
<service
android:name="com.geeksville.mesh.MeshService"
android:name="com.geeksville.mesh.service.MeshService"
android:enabled="true"
android:exported="true">
<intent-filter>
@ -70,7 +70,7 @@
<!-- This is a private service which just does direct communication to the radio -->
<service
android:name="com.geeksville.mesh.RadioInterfaceService"
android:name="com.geeksville.mesh.service.RadioInterfaceService"
android:enabled="true"
android:exported="false" />
@ -85,7 +85,7 @@
</intent-filter>
</activity>
<receiver android:name="com.geeksville.mesh.BootCompleteReceiver">
<receiver android:name="com.geeksville.mesh.service.BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>

Wyświetl plik

@ -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

Wyświetl plik

@ -1,4 +1,4 @@
package com.geeksville.mesh
package com.geeksville.mesh.service
import android.content.BroadcastReceiver
import android.content.Context

Wyświetl plik

@ -1,4 +1,4 @@
package com.geeksville.mesh
package com.geeksville.mesh.service
const val prefix = "com.geeksville.mesh"

Wyświetl plik

@ -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<Int, NodeInfo>()
@ -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()
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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 <T> queueWork(tag: String, cont: Continuation<T>, 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<BluetoothGattCharacteristic>
) = 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<BluetoothGattCharacteristic>
) = queueWork("writeC", cont) { gatt!!.writeCharacteristic(c) }
) = queueWork("writeC ${c.uuid}", cont) { gatt!!.writeCharacteristic(c) }
fun asyncWriteCharacteristic(
c: BluetoothGattCharacteristic,

Wyświetl plik

@ -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
)
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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
)