mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
split out common code for USB and BLE links
This commit is contained in:
parent
54c832f591
commit
cecc369598
7 changed files with 255 additions and 169 deletions
|
|
@ -40,6 +40,9 @@
|
|||
<uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND" />
|
||||
<uses-permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND" />
|
||||
|
||||
<!-- Uart access -->
|
||||
<uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />
|
||||
|
||||
<!-- the xing library will try to bring this permission in but we don't want it -->
|
||||
<uses-permission
|
||||
android:name="android.permission.CAMERA"
|
||||
|
|
@ -97,10 +100,16 @@
|
|||
|
||||
<!-- This is a private service which just does direct communication to the radio -->
|
||||
<service
|
||||
android:name="com.geeksville.mesh.service.RadioInterfaceService"
|
||||
android:name="com.geeksville.mesh.service.BluetoothInterfaceService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
|
||||
<!-- This is a private service which just does direct communication to the radio -->
|
||||
<!-- <service
|
||||
android:name="com.geeksville.mesh.service.SerialInterfaceService"
|
||||
android:enabled="true"
|
||||
android:exported="false" /> -->
|
||||
|
||||
<activity
|
||||
android:name="com.geeksville.mesh.MainActivity"
|
||||
android:label="@string/app_name"
|
||||
|
|
|
|||
|
|
@ -734,7 +734,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
bindMeshService()
|
||||
|
||||
val bonded =
|
||||
RadioInterfaceService.getBondedDeviceAddress(this) != null
|
||||
BluetoothInterfaceService.getBondedDeviceAddress(this) != null
|
||||
if (!bonded)
|
||||
pager.currentItem = 5
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,21 @@
|
|||
package com.geeksville.mesh.service
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Service
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothGattService
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.companion.CompanionDeviceManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import android.os.RemoteException
|
||||
import androidx.core.content.edit
|
||||
import com.geeksville.analytics.DataPair
|
||||
import com.geeksville.android.BinaryLogFile
|
||||
import com.geeksville.android.GeeksvilleApplication
|
||||
import com.geeksville.android.Logging
|
||||
import com.geeksville.concurrent.DeferredExecution
|
||||
import com.geeksville.concurrent.handledLaunch
|
||||
import com.geeksville.mesh.IRadioInterfaceService
|
||||
import com.geeksville.util.anonymize
|
||||
import com.geeksville.util.exceptionReporter
|
||||
import com.geeksville.util.ignoreException
|
||||
import com.geeksville.util.toRemoteExceptions
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import java.lang.reflect.Method
|
||||
import java.util.*
|
||||
|
|
@ -90,8 +80,6 @@ A variable keepAllPackets, if set to true will suppress this behavior and instea
|
|||
*/
|
||||
|
||||
|
||||
class RadioNotConnectedException(message: String = "Not connected to radio") :
|
||||
BLEException(message)
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -103,66 +91,21 @@ class RadioNotConnectedException(message: String = "Not connected to radio") :
|
|||
* Note - this class intentionally dumb. It doesn't understand protobuf framing etc...
|
||||
* It is designed to be simple so it can be stubbed out with a simulated version as needed.
|
||||
*/
|
||||
class RadioInterfaceService : Service(), Logging {
|
||||
class BluetoothInterfaceService : InterfaceService() {
|
||||
|
||||
companion object : Logging {
|
||||
/**
|
||||
* The RECEIVED_FROMRADIO
|
||||
* Payload will be the raw bytes which were contained within a MeshProtos.FromRadio protobuf
|
||||
*/
|
||||
const val RECEIVE_FROMRADIO_ACTION = "$prefix.RECEIVE_FROMRADIO"
|
||||
|
||||
/**
|
||||
* This is broadcast when connection state changed
|
||||
*/
|
||||
const val RADIO_CONNECTED_ACTION = "$prefix.CONNECT_CHANGED"
|
||||
|
||||
/// this service UUID is publically visible for scanning
|
||||
val BTM_SERVICE_UUID = UUID.fromString("6ba1b218-15a8-461f-9fa8-5dcae273eafd")
|
||||
|
||||
private val BTM_FROMRADIO_CHARACTER =
|
||||
UUID.fromString("8ba2bcc2-ee02-4a55-a531-c525c5e454d5")
|
||||
private val BTM_TORADIO_CHARACTER =
|
||||
UUID.fromString("f75c76d2-129e-4dad-a1dd-7866124401e7")
|
||||
private val BTM_FROMNUM_CHARACTER =
|
||||
UUID.fromString("ed9da18c-a800-4f66-a670-aa7547e34453")
|
||||
|
||||
/// mynode - read/write this to access a MyNodeInfo protobuf
|
||||
private val BTM_MYNODE_CHARACTER =
|
||||
UUID.fromString("ea9f3f82-8dc4-4733-9452-1f6da28892a2")
|
||||
|
||||
/// nodeinfo - read this to get a series of node infos (ending with a null empty record), write to this to restart the read statemachine that returns all the node infos
|
||||
private val BTM_NODEINFO_CHARACTER =
|
||||
UUID.fromString("d31e02e0-c8ab-4d3f-9cc9-0b8466bdabe8")
|
||||
|
||||
/// radio - read/write this to access a RadioConfig protobuf
|
||||
private val BTM_RADIO_CHARACTER =
|
||||
UUID.fromString("b56786c8-839a-44a1-b98e-a1724c4a0262")
|
||||
|
||||
/// owner - read/write this to access a User protobuf
|
||||
private val BTM_OWNER_CHARACTER =
|
||||
UUID.fromString("6ff1d8b6-e2de-41e3-8c0b-8fa384f64eb6")
|
||||
|
||||
private const val DEVADDR_KEY = "devAddr"
|
||||
|
||||
/// If our service is currently running, this pointer can be used to reach it (in case setBondedDeviceAddress is called)
|
||||
private var runningService: RadioInterfaceService? = null
|
||||
private var runningService: BluetoothInterfaceService? = null
|
||||
|
||||
/**
|
||||
* Temp hack (until old API deprecated), try using just the new API now
|
||||
*/
|
||||
var isOldApi: Boolean? = false
|
||||
|
||||
/// This is public only so that SimRadio can bootstrap our message flow
|
||||
fun broadcastReceivedFromRadio(context: Context, payload: ByteArray) {
|
||||
val intent = Intent(RECEIVE_FROMRADIO_ACTION)
|
||||
intent.putExtra(EXTRA_PAYLOAD, payload)
|
||||
context.sendBroadcast(intent)
|
||||
}
|
||||
|
||||
private fun getPrefs(context: Context) =
|
||||
context.getSharedPreferences("radio-prefs", Context.MODE_PRIVATE)
|
||||
|
||||
/// Get our bluetooth adapter (should always succeed except on emulator
|
||||
private fun getBluetoothAdapter(context: Context): BluetoothAdapter? {
|
||||
val bluetoothManager =
|
||||
|
|
@ -226,32 +169,8 @@ class RadioInterfaceService : Service(), Logging {
|
|||
get(): BluetoothGattService = device.getService(BTM_SERVICE_UUID)
|
||||
?: throw RadioNotConnectedException("BLE service not found")
|
||||
|
||||
//.services.find { it.uuid == BTM_SERVICE_UUID }!!
|
||||
|
||||
private lateinit var fromNum: BluetoothGattCharacteristic
|
||||
|
||||
private val logSends = false
|
||||
private val logReceives = false
|
||||
lateinit var sentPacketsLog: BinaryLogFile // inited in onCreate
|
||||
lateinit var receivedPacketsLog: BinaryLogFile
|
||||
|
||||
private var isConnected = false
|
||||
|
||||
private val serviceJob = Job()
|
||||
private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
|
||||
|
||||
/// Work that users of our service want done, which might get deferred until after
|
||||
/// we have completed our initial connection
|
||||
private val clientOperations = DeferredExecution()
|
||||
|
||||
private fun broadcastConnectionChanged(isConnected: Boolean, isPermanent: Boolean) {
|
||||
debug("Broadcasting connection=$isConnected")
|
||||
val intent = Intent(RADIO_CONNECTED_ACTION)
|
||||
intent.putExtra(EXTRA_CONNECTED, isConnected)
|
||||
intent.putExtra(EXTRA_PERMANENT, isPermanent)
|
||||
sendBroadcast(intent)
|
||||
}
|
||||
|
||||
/**
|
||||
* With the new rev2 api, our first send is to start the configure readbacks. In that case,
|
||||
* rather than waiting for FromNum notifies - we try to just aggressively read all of the responses.
|
||||
|
|
@ -259,7 +178,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
private var isFirstSend = true
|
||||
|
||||
/// Send a packet/command out the radio link
|
||||
private fun handleSendToRadio(p: ByteArray) {
|
||||
override fun handleSendToRadio(p: ByteArray) {
|
||||
// Do this in the IO thread because it might take a while (and we don't care about the result code)
|
||||
serviceScope.handledLaunch {
|
||||
try {
|
||||
|
|
@ -283,18 +202,6 @@ class RadioInterfaceService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
// Handle an incoming packet from the radio, broadcasts it as an android intent
|
||||
private fun handleFromRadio(p: ByteArray) {
|
||||
if (logReceives) {
|
||||
receivedPacketsLog.write(p)
|
||||
receivedPacketsLog.flush()
|
||||
}
|
||||
|
||||
broadcastReceivedFromRadio(
|
||||
this,
|
||||
p
|
||||
)
|
||||
}
|
||||
|
||||
/// Attempt to read from the fromRadio mailbox, if data is found broadcast it to android apps
|
||||
private fun doReadFromRadio(firstRead: Boolean) {
|
||||
|
|
@ -331,7 +238,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
fun setBondedDeviceAddress(addr: String?) {
|
||||
override fun setBondedDeviceAddress(addr: String?) {
|
||||
// Record that this use has configured a radio
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"mesh_bond"
|
||||
|
|
@ -373,11 +280,6 @@ class RadioInterfaceService : Service(), Logging {
|
|||
}
|
||||
|
||||
|
||||
private fun onDisconnect(isPermanent: Boolean) {
|
||||
broadcastConnectionChanged(false, isPermanent)
|
||||
isConnected = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Android caches old services. But our service is still changing often, so force it to reread the service definitions every
|
||||
* time
|
||||
|
|
@ -519,21 +421,15 @@ class RadioInterfaceService : Service(), Logging {
|
|||
override fun onCreate() {
|
||||
runningService = this
|
||||
super.onCreate()
|
||||
setEnabled(true)
|
||||
registerReceiver(bluetoothStateReceiver, bluetoothStateReceiver.intent)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
unregisterReceiver(bluetoothStateReceiver)
|
||||
setEnabled(false)
|
||||
serviceJob.cancel()
|
||||
runningService = null
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
return binder;
|
||||
}
|
||||
|
||||
/// Start a connection attempt
|
||||
private fun startConnect() {
|
||||
|
|
@ -547,7 +443,8 @@ class RadioInterfaceService : Service(), Logging {
|
|||
}
|
||||
|
||||
/// Open or close a bluetooth connection to our device
|
||||
private fun setEnabled(on: Boolean) {
|
||||
override fun setEnabled(on: Boolean) {
|
||||
super.setEnabled(on)
|
||||
if (on) {
|
||||
if (safe != null) {
|
||||
info("Skipping radio enable, it is already on")
|
||||
|
|
@ -570,11 +467,6 @@ class RadioInterfaceService : Service(), Logging {
|
|||
} else {
|
||||
errormsg("Bluetooth adapter not found, assuming running on the emulator!")
|
||||
}
|
||||
|
||||
if (logSends)
|
||||
sentPacketsLog = BinaryLogFile(this, "sent_log.pb")
|
||||
if (logReceives)
|
||||
receivedPacketsLog = BinaryLogFile(this, "receive_log.pb")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -584,12 +476,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
safe =
|
||||
null // We do this first, because if we throw we still want to mark that we no longer have a valid connection
|
||||
|
||||
if (logSends)
|
||||
sentPacketsLog.close()
|
||||
if (logReceives)
|
||||
receivedPacketsLog.close()
|
||||
s?.close()
|
||||
onDisconnect(isPermanent = true) // Tell any clients we are now offline
|
||||
} else {
|
||||
debug("Radio was not connected, skipping disable")
|
||||
}
|
||||
|
|
@ -599,7 +486,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
/**
|
||||
* do a synchronous write operation
|
||||
*/
|
||||
private fun doWrite(uuid: UUID, a: ByteArray) = toRemoteExceptions {
|
||||
override fun doWrite(uuid: UUID, a: ByteArray) = toRemoteExceptions {
|
||||
if (!isConnected)
|
||||
throw RadioNotConnectedException()
|
||||
else {
|
||||
|
|
@ -625,7 +512,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
* do an asynchronous write operation
|
||||
* Any error responses will be ignored (other than log messages)
|
||||
*/
|
||||
private fun doAsyncWrite(uuid: UUID, a: ByteArray) = toRemoteExceptions {
|
||||
override fun doAsyncWrite(uuid: UUID, a: ByteArray) = toRemoteExceptions {
|
||||
if (!isConnected)
|
||||
throw RadioNotConnectedException()
|
||||
else {
|
||||
|
|
@ -645,7 +532,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
/**
|
||||
* do a synchronous read operation
|
||||
*/
|
||||
private fun doRead(uuid: UUID): ByteArray? = toRemoteExceptions {
|
||||
override fun doRead(uuid: UUID): ByteArray? = toRemoteExceptions {
|
||||
if (!isConnected)
|
||||
throw RadioNotConnectedException()
|
||||
else {
|
||||
|
|
@ -663,32 +550,4 @@ class RadioInterfaceService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
private val binder = object : IRadioInterfaceService.Stub() {
|
||||
|
||||
override fun setDeviceAddress(deviceAddr: String?) = toRemoteExceptions {
|
||||
setBondedDeviceAddress(deviceAddr)
|
||||
}
|
||||
|
||||
// A write of any size to nodeinfo means restart reading
|
||||
override fun restartNodeInfo() = doWrite(BTM_NODEINFO_CHARACTER, ByteArray(0))
|
||||
|
||||
override fun readMyNode() =
|
||||
doRead(BTM_MYNODE_CHARACTER)
|
||||
?: throw RemoteException("Device returned empty MyNodeInfo")
|
||||
|
||||
override fun sendToRadio(a: ByteArray) = handleSendToRadio(a)
|
||||
|
||||
override fun readRadioConfig() =
|
||||
doRead(BTM_RADIO_CHARACTER)
|
||||
?: throw RemoteException("Device returned empty RadioConfig")
|
||||
|
||||
override fun readOwner() =
|
||||
doRead(BTM_OWNER_CHARACTER) ?: throw RemoteException("Device returned empty Owner")
|
||||
|
||||
override fun writeOwner(owner: ByteArray) = doWrite(BTM_OWNER_CHARACTER, owner)
|
||||
|
||||
override fun writeRadioConfig(config: ByteArray) = doWrite(BTM_RADIO_CHARACTER, config)
|
||||
|
||||
override fun readNodeInfo() = doRead(BTM_NODEINFO_CHARACTER)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
package com.geeksville.mesh.service
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import android.os.RemoteException
|
||||
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 kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import java.util.*
|
||||
|
||||
|
||||
class RadioNotConnectedException(message: String = "Not connected to radio") :
|
||||
BLEException(message)
|
||||
|
||||
|
||||
/**
|
||||
* Handles the bluetooth link with a mesh radio device. Does not cache any device state,
|
||||
* just does bluetooth comms etc...
|
||||
*
|
||||
* This service is not exposed outside of this process.
|
||||
*
|
||||
* Note - this class intentionally dumb. It doesn't understand protobuf framing etc...
|
||||
* It is designed to be simple so it can be stubbed out with a simulated version as needed.
|
||||
*/
|
||||
abstract class InterfaceService : Service(), Logging {
|
||||
|
||||
companion object : Logging {
|
||||
/**
|
||||
* The RECEIVED_FROMRADIO
|
||||
* Payload will be the raw bytes which were contained within a MeshProtos.FromRadio protobuf
|
||||
*/
|
||||
const val RECEIVE_FROMRADIO_ACTION = "$prefix.RECEIVE_FROMRADIO"
|
||||
|
||||
/**
|
||||
* This is broadcast when connection state changed
|
||||
*/
|
||||
const val RADIO_CONNECTED_ACTION = "$prefix.CONNECT_CHANGED"
|
||||
|
||||
const val DEVADDR_KEY = "devAddr"
|
||||
|
||||
val BTM_FROMRADIO_CHARACTER =
|
||||
UUID.fromString("8ba2bcc2-ee02-4a55-a531-c525c5e454d5")
|
||||
val BTM_TORADIO_CHARACTER =
|
||||
UUID.fromString("f75c76d2-129e-4dad-a1dd-7866124401e7")
|
||||
val BTM_FROMNUM_CHARACTER =
|
||||
UUID.fromString("ed9da18c-a800-4f66-a670-aa7547e34453")
|
||||
|
||||
/// mynode - read/write this to access a MyNodeInfo protobuf
|
||||
val BTM_MYNODE_CHARACTER =
|
||||
UUID.fromString("ea9f3f82-8dc4-4733-9452-1f6da28892a2")
|
||||
|
||||
/// nodeinfo - read this to get a series of node infos (ending with a null empty record), write to this to restart the read statemachine that returns all the node infos
|
||||
val BTM_NODEINFO_CHARACTER =
|
||||
UUID.fromString("d31e02e0-c8ab-4d3f-9cc9-0b8466bdabe8")
|
||||
|
||||
/// radio - read/write this to access a RadioConfig protobuf
|
||||
val BTM_RADIO_CHARACTER =
|
||||
UUID.fromString("b56786c8-839a-44a1-b98e-a1724c4a0262")
|
||||
|
||||
/// owner - read/write this to access a User protobuf
|
||||
val BTM_OWNER_CHARACTER =
|
||||
UUID.fromString("6ff1d8b6-e2de-41e3-8c0b-8fa384f64eb6")
|
||||
|
||||
/// This is public only so that SimRadio can bootstrap our message flow
|
||||
fun broadcastReceivedFromRadio(context: Context, payload: ByteArray) {
|
||||
val intent = Intent(RECEIVE_FROMRADIO_ACTION)
|
||||
intent.putExtra(EXTRA_PAYLOAD, payload)
|
||||
context.sendBroadcast(intent)
|
||||
}
|
||||
|
||||
fun getPrefs(context: Context) =
|
||||
context.getSharedPreferences("radio-prefs", Context.MODE_PRIVATE)
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected val logSends = false
|
||||
protected val logReceives = false
|
||||
protected lateinit var sentPacketsLog: BinaryLogFile // inited in onCreate
|
||||
protected lateinit var receivedPacketsLog: BinaryLogFile
|
||||
|
||||
protected var isConnected = false
|
||||
|
||||
private val serviceJob = Job()
|
||||
protected val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
|
||||
|
||||
/// Work that users of our service want done, which might get deferred until after
|
||||
/// we have completed our initial connection
|
||||
private val clientOperations = DeferredExecution()
|
||||
|
||||
protected fun broadcastConnectionChanged(isConnected: Boolean, isPermanent: Boolean) {
|
||||
debug("Broadcasting connection=$isConnected")
|
||||
val intent = Intent(RADIO_CONNECTED_ACTION)
|
||||
intent.putExtra(EXTRA_CONNECTED, isConnected)
|
||||
intent.putExtra(EXTRA_PERMANENT, isPermanent)
|
||||
sendBroadcast(intent)
|
||||
}
|
||||
|
||||
/**
|
||||
* With the new rev2 api, our first send is to start the configure readbacks. In that case,
|
||||
* rather than waiting for FromNum notifies - we try to just aggressively read all of the responses.
|
||||
*/
|
||||
private var isFirstSend = true
|
||||
|
||||
/// Send a packet/command out the radio link
|
||||
protected abstract fun handleSendToRadio(p: ByteArray)
|
||||
|
||||
// Handle an incoming packet from the radio, broadcasts it as an android intent
|
||||
protected fun handleFromRadio(p: ByteArray) {
|
||||
if (logReceives) {
|
||||
receivedPacketsLog.write(p)
|
||||
receivedPacketsLog.flush()
|
||||
}
|
||||
|
||||
broadcastReceivedFromRadio(
|
||||
this,
|
||||
p
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
protected fun onDisconnect(isPermanent: Boolean) {
|
||||
broadcastConnectionChanged(false, isPermanent)
|
||||
isConnected = false
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
setEnabled(true)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
setEnabled(false)
|
||||
serviceJob.cancel()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
return binder;
|
||||
}
|
||||
|
||||
|
||||
/// Open or close a bluetooth connection to our device
|
||||
protected open fun setEnabled(on: Boolean) {
|
||||
if (on) {
|
||||
if (logSends)
|
||||
sentPacketsLog = BinaryLogFile(this, "sent_log.pb")
|
||||
if (logReceives)
|
||||
receivedPacketsLog = BinaryLogFile(this, "receive_log.pb")
|
||||
} else {
|
||||
if (logSends)
|
||||
sentPacketsLog.close()
|
||||
if (logReceives)
|
||||
receivedPacketsLog.close()
|
||||
|
||||
onDisconnect(isPermanent = true) // Tell any clients we are now offline
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* do a synchronous write operation
|
||||
*/
|
||||
protected abstract fun doWrite(uuid: UUID, a: ByteArray)
|
||||
|
||||
/**
|
||||
* do an asynchronous write operation
|
||||
* Any error responses will be ignored (other than log messages)
|
||||
*/
|
||||
protected abstract fun doAsyncWrite(uuid: UUID, a: ByteArray)
|
||||
|
||||
protected abstract fun setBondedDeviceAddress(addr: String?)
|
||||
|
||||
/**
|
||||
* do a synchronous read operation
|
||||
*/
|
||||
protected abstract fun doRead(uuid: UUID): ByteArray?
|
||||
|
||||
private val binder = object : IRadioInterfaceService.Stub() {
|
||||
|
||||
override fun setDeviceAddress(deviceAddr: String?) = toRemoteExceptions {
|
||||
setBondedDeviceAddress(deviceAddr)
|
||||
}
|
||||
|
||||
override fun sendToRadio(a: ByteArray) = handleSendToRadio(a)
|
||||
|
||||
//
|
||||
// NOTE: the following methods are all deprecated and will be removed soon
|
||||
//
|
||||
|
||||
// A write of any size to nodeinfo means restart reading
|
||||
override fun restartNodeInfo() = doWrite(BTM_NODEINFO_CHARACTER, ByteArray(0))
|
||||
|
||||
override fun readMyNode() =
|
||||
doRead(BTM_MYNODE_CHARACTER)
|
||||
?: throw RemoteException("Device returned empty MyNodeInfo")
|
||||
|
||||
override fun readRadioConfig() =
|
||||
doRead(BTM_RADIO_CHARACTER)
|
||||
?: throw RemoteException("Device returned empty RadioConfig")
|
||||
|
||||
override fun readOwner() =
|
||||
doRead(BTM_OWNER_CHARACTER) ?: throw RemoteException("Device returned empty Owner")
|
||||
|
||||
override fun writeOwner(owner: ByteArray) = doWrite(BTM_OWNER_CHARACTER, owner)
|
||||
override fun writeRadioConfig(config: ByteArray) = doWrite(BTM_RADIO_CHARACTER, config)
|
||||
|
||||
override fun readNodeInfo() = doRead(BTM_NODEINFO_CHARACTER)
|
||||
}
|
||||
}
|
||||
|
|
@ -445,12 +445,12 @@ 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.RADIO_CONNECTED_ACTION)
|
||||
filter.addAction(InterfaceService.RECEIVE_FROMRADIO_ACTION)
|
||||
filter.addAction(InterfaceService.RADIO_CONNECTED_ACTION)
|
||||
registerReceiver(radioInterfaceReceiver, filter)
|
||||
|
||||
// We in turn need to use the radiointerface service
|
||||
val intent = Intent(this@MeshService, RadioInterfaceService::class.java)
|
||||
val intent = Intent(this@MeshService, BluetoothInterfaceService::class.java)
|
||||
// intent.action = IMeshService::class.java.name
|
||||
radio.connect(this@MeshService, intent, Context.BIND_AUTO_CREATE)
|
||||
|
||||
|
|
@ -1060,7 +1060,7 @@ class MeshService : Service(), Logging {
|
|||
// Do our startup init
|
||||
try {
|
||||
connectTimeMsec = System.currentTimeMillis()
|
||||
if (RadioInterfaceService.isOldApi!!)
|
||||
if (BluetoothInterfaceService.isOldApi!!)
|
||||
reinitFromRadioREV1()
|
||||
else
|
||||
startConfig()
|
||||
|
|
@ -1126,7 +1126,7 @@ class MeshService : Service(), Logging {
|
|||
serviceScope.handledLaunch {
|
||||
debug("Received broadcast ${intent.action}")
|
||||
when (intent.action) {
|
||||
RadioInterfaceService.RADIO_CONNECTED_ACTION -> {
|
||||
InterfaceService.RADIO_CONNECTED_ACTION -> {
|
||||
try {
|
||||
val connected = intent.getBooleanExtra(EXTRA_CONNECTED, false)
|
||||
val permanent = intent.getBooleanExtra(EXTRA_PERMANENT, false)
|
||||
|
|
@ -1143,7 +1143,7 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
RadioInterfaceService.RECEIVE_FROMRADIO_ACTION -> {
|
||||
InterfaceService.RECEIVE_FROMRADIO_ACTION -> {
|
||||
val proto =
|
||||
MeshProtos.FromRadio.parseFrom(
|
||||
intent.getByteArrayExtra(
|
||||
|
|
@ -1348,7 +1348,7 @@ class MeshService : Service(), Logging {
|
|||
val parsed = MeshProtos.RadioConfig.parseFrom(payload)
|
||||
|
||||
// Update our device
|
||||
if (RadioInterfaceService.isOldApi!!)
|
||||
if (BluetoothInterfaceService.isOldApi!!)
|
||||
connectedRadio.writeRadioConfig(payload)
|
||||
else
|
||||
sendToRadio(ToRadio.newBuilder().apply {
|
||||
|
|
@ -1378,7 +1378,7 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
|
||||
// set my owner info
|
||||
if (RadioInterfaceService.isOldApi!!)
|
||||
if (BluetoothInterfaceService.isOldApi!!)
|
||||
connectedRadio.writeOwner(user.toByteArray())
|
||||
else sendToRadio(ToRadio.newBuilder().apply {
|
||||
this.setOwner = user
|
||||
|
|
@ -1449,7 +1449,8 @@ class MeshService : Service(), Logging {
|
|||
// Run in the IO thread
|
||||
val filename = firmwareUpdateFilename ?: throw Exception("No update filename")
|
||||
val safe =
|
||||
RadioInterfaceService.safe ?: throw Exception("Can't update - no bluetooth connected")
|
||||
BluetoothInterfaceService.safe
|
||||
?: throw Exception("Can't update - no bluetooth connected")
|
||||
|
||||
serviceScope.handledLaunch {
|
||||
SoftwareUpdateService.doUpdate(this@MeshService, safe, filename)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.geeksville.mesh
|
||||
|
||||
import android.content.Context
|
||||
import com.geeksville.mesh.service.RadioInterfaceService
|
||||
import com.geeksville.mesh.service.InterfaceService
|
||||
|
||||
class SimRadio(private val context: Context) {
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ class SimRadio(private val context: Context) {
|
|||
}.build()
|
||||
}.build()
|
||||
|
||||
RadioInterfaceService.broadcastReceivedFromRadio(context, fromRadio.toByteArray())
|
||||
InterfaceService.broadcastReceivedFromRadio(context, fromRadio.toByteArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,8 +29,8 @@ import com.geeksville.concurrent.handledLaunch
|
|||
import com.geeksville.mesh.MainActivity
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.model.UIViewModel
|
||||
import com.geeksville.mesh.service.BluetoothInterfaceService
|
||||
import com.geeksville.mesh.service.MeshService
|
||||
import com.geeksville.mesh.service.RadioInterfaceService
|
||||
import com.geeksville.util.anonymize
|
||||
import com.geeksville.util.exceptionReporter
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
|
@ -176,7 +176,7 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
|
|||
*/
|
||||
fun startScan(): Boolean {
|
||||
debug("BTScan component active")
|
||||
selectedMacAddr = RadioInterfaceService.getBondedDeviceAddress(context)
|
||||
selectedMacAddr = BluetoothInterfaceService.getBondedDeviceAddress(context)
|
||||
|
||||
return if (bluetoothAdapter == null) {
|
||||
warn("No bluetooth adapter. Running under emulation?")
|
||||
|
|
@ -212,7 +212,7 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
|
|||
// filter and only accept devices that have a sw update service
|
||||
val filter =
|
||||
ScanFilter.Builder()
|
||||
.setServiceUuid(ParcelUuid(RadioInterfaceService.BTM_SERVICE_UUID))
|
||||
.setServiceUuid(ParcelUuid(BluetoothInterfaceService.BTM_SERVICE_UUID))
|
||||
.build()
|
||||
|
||||
val settings =
|
||||
|
|
@ -301,7 +301,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
|
||||
|
||||
private val hasCompanionDeviceApi: Boolean by lazy {
|
||||
RadioInterfaceService.hasCompanionDeviceApi(requireContext())
|
||||
BluetoothInterfaceService.hasCompanionDeviceApi(requireContext())
|
||||
}
|
||||
|
||||
private val deviceManager: CompanionDeviceManager by lazy {
|
||||
|
|
@ -507,7 +507,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
}
|
||||
|
||||
val hasBonded =
|
||||
RadioInterfaceService.getBondedDeviceAddress(requireContext()) != null
|
||||
BluetoothInterfaceService.getBondedDeviceAddress(requireContext()) != null
|
||||
|
||||
// get rid of the warning text once at least one device is paired
|
||||
warningNotPaired.visibility = if (hasBonded) View.GONE else View.VISIBLE
|
||||
|
|
@ -571,7 +571,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
deviceRadioGroup.visibility = View.GONE
|
||||
changeRadioButton.visibility = View.VISIBLE
|
||||
|
||||
val curRadio = RadioInterfaceService.getBondedDeviceAddress(requireContext())
|
||||
val curRadio = BluetoothInterfaceService.getBondedDeviceAddress(requireContext())
|
||||
|
||||
if (curRadio != null) {
|
||||
scanStatusText.text = getString(R.string.current_pair).format(curRadio)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue