From 674b417c8732e1bbf29023974781989eb5ecda32 Mon Sep 17 00:00:00 2001 From: geeksville Date: Mon, 24 Feb 2020 18:10:25 -0800 Subject: [PATCH] BLE software update works again --- TODO.md | 2 + .../mesh/IRadioInterfaceService.aidl | 3 + .../geeksville/mesh/service/MeshService.kt | 3 +- .../mesh/service/RadioInterfaceService.kt | 77 +++++++++++-------- 4 files changed, 50 insertions(+), 35 deletions(-) diff --git a/TODO.md b/TODO.md index f24e9888a..d530f211a 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,7 @@ # High priority MVP features required for first public alpha +* "new bluetooth connection state 0, status 22" loss of connection * make a boot screen explaining this is an early alpha * describe user experience: devices always point to each other and show distance, you can send texts between nodes the channel is encrypted, you can share the the channel key with others by qr code or by sharing a special link @@ -62,6 +63,7 @@ Do this "Signal app compatible" release relatively soon after the alpha release # Medium priority Things for the betaish period. +* make sw update work while node is connected to mesh (at least shutdown the other bluetooth services) * Use LocationRequest.setSmallestDisplacement to save battery and decrease net activity * MeshService.reinitFromRadio can take 300 ms, run it in a worker thread instead * show user icons in chat diff --git a/app/src/main/aidl/com/geeksville/mesh/IRadioInterfaceService.aidl b/app/src/main/aidl/com/geeksville/mesh/IRadioInterfaceService.aidl index f02b56149..b7aa04e01 100644 --- a/app/src/main/aidl/com/geeksville/mesh/IRadioInterfaceService.aidl +++ b/app/src/main/aidl/com/geeksville/mesh/IRadioInterfaceService.aidl @@ -21,4 +21,7 @@ interface IRadioInterfaceService { /// owner - read/write this to access a User protobuf byte []readOwner(); void writeOwner(in byte [] owner); + + /// If true we will try to talk to our device, if false we will shutdown. Useful during software update. + void enableLink(boolean enable); } 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 d4d1e1a65..019be0cb9 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -153,7 +153,7 @@ class MeshService : Service(), Logging { if (fusedLocationClient == null) { val request = LocationRequest.create().apply { interval = - 10 * 1000 // FIXME, do more like once every 5 mins while we are connected to our radio _and_ someone else is in the mesh + 5 * 60 * 1000 // FIXME, do more like once every 5 mins while we are connected to our radio _and_ someone else is in the mesh priority = LocationRequest.PRIORITY_HIGH_ACCURACY } @@ -186,7 +186,6 @@ class MeshService : Service(), Logging { val client = LocationServices.getFusedLocationProviderClient(this) - // FIXME - should we use Looper.myLooper() in the third param per https://github.com/android/location-samples/blob/432d3b72b8c058f220416958b444274ddd186abd/LocationUpdatesForegroundService/app/src/main/java/com/google/android/gms/location/sample/locationupdatesforegroundservice/LocationUpdatesService.java client.requestLocationUpdates(request, locationCallback, null) diff --git a/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt index 36bb8a575..0ae356ddf 100644 --- a/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt @@ -275,42 +275,11 @@ class RadioInterfaceService : Service(), Logging { override fun onCreate() { super.onCreate() - - // FIXME, let user GUI select which device we are talking to - - val address = getBondedDeviceAddress(this) - if (address == null) - error("No bonded mesh radio, can't create service") - else { - // Note: this call does no comms, it just creates the device object (even if the - // device is off/not connected) - val device = getBluetoothAdapter(this)?.getRemoteDevice(address) - if (device != null) { - info("Creating radio interface service. device=$address") - - // Note this constructor also does no comm - val s = SafeBluetooth(this, device) - safe = s - - // FIXME, pass in true for autoconnect - so we will autoconnect whenever the radio - // comes in range (even if we made this connect call long ago when we got powered on) - // see https://stackoverflow.com/questions/40156699/which-correct-flag-of-autoconnect-in-connectgatt-of-ble for - // more info - s.asyncConnect(true, ::onConnect, ::onDisconnect) - } else { - error("Bluetooth adapter not found, assuming running on the emulator!") - } - - if (logSends) - sentPacketsLog = BinaryLogFile(this, "sent_log.pb") - } + setEnabled(true) } override fun onDestroy() { - info("Destroying radio interface service") - if (logSends) - sentPacketsLog.close() - safe?.close() + setEnabled(false) super.onDestroy() } @@ -318,6 +287,44 @@ class RadioInterfaceService : Service(), Logging { return binder; } + /// Open or close a bluetooth connection to our device + private fun setEnabled(on: Boolean) { + if (on) { + val address = getBondedDeviceAddress(this) + if (address == null) + error("No bonded mesh radio, can't create service") + else { + // Note: this call does no comms, it just creates the device object (even if the + // device is off/not connected) + val device = getBluetoothAdapter(this)?.getRemoteDevice(address) + if (device != null) { + info("Creating radio interface service. device=$address") + + // Note this constructor also does no comm + val s = SafeBluetooth(this, device) + safe = s + + // FIXME, pass in true for autoconnect - so we will autoconnect whenever the radio + // comes in range (even if we made this connect call long ago when we got powered on) + // see https://stackoverflow.com/questions/40156699/which-correct-flag-of-autoconnect-in-connectgatt-of-ble for + // more info + s.asyncConnect(true, ::onConnect, ::onDisconnect) + } else { + error("Bluetooth adapter not found, assuming running on the emulator!") + } + + if (logSends) + sentPacketsLog = BinaryLogFile(this, "sent_log.pb") + } + } else { + info("Closing radio interface service") + if (logSends) + sentPacketsLog.close() + safe?.close() + safe = null + } + } + /** * do a synchronous write operation */ @@ -379,6 +386,10 @@ class RadioInterfaceService : Service(), Logging { } private val binder = object : IRadioInterfaceService.Stub() { + override fun enableLink(enable: Boolean) = toRemoteExceptions { + setEnabled(enable) + } + // A write of any size to nodeinfo means restart reading override fun restartNodeInfo() = doWrite(BTM_NODEINFO_CHARACTER, ByteArray(0))