set aside ble sw update for now

pull/40/head
geeksville 2020-05-15 10:18:15 -07:00
rodzic 3c338aec61
commit c06f5f1c39
4 zmienionych plików z 79 dodań i 29 usunięć

Wyświetl plik

@ -226,12 +226,27 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
completeWork(status, characteristic)
}
override fun onReliableWriteCompleted(gatt: BluetoothGatt, status: Int) {
completeWork(status, Unit)
}
override fun onCharacteristicWrite(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic,
status: Int
) {
completeWork(status, characteristic)
val reliable = currentReliableWrite
if (reliable != null)
if (!characteristic.value.contentEquals(reliable)) {
errormsg("A reliable write failed!")
gatt.abortReliableWrite();
completeWork(42, characteristic) // skanky code to indicate failure
} else {
logAssert(gatt.executeReliableWrite())
// After this execute reliable completes - we can continue with normal operations (see onReliableWriteCompleted)
}
else // Just a standard write - do the normal flow
completeWork(status, characteristic)
}
override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) {
@ -481,10 +496,15 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
fun requestMtu(len: Int): Unit = makeSync { queueRequestMtu(len, it) }
private var currentReliableWrite: ByteArray? = null
private fun queueWriteCharacteristic(
c: BluetoothGattCharacteristic,
cont: Continuation<BluetoothGattCharacteristic>
) = queueWork("writeC ${c.uuid}", cont) { gatt!!.writeCharacteristic(c) }
) = queueWork("writeC ${c.uuid}", cont) {
currentReliableWrite = null
gatt!!.writeCharacteristic(c)
}
fun asyncWriteCharacteristic(
c: BluetoothGattCharacteristic,
@ -494,6 +514,26 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
fun writeCharacteristic(c: BluetoothGattCharacteristic): BluetoothGattCharacteristic =
makeSync { queueWriteCharacteristic(c, it) }
/** Like write, but we use the extra reliable flow documented here:
* https://stackoverflow.com/questions/24485536/what-is-reliable-write-in-ble
*/
private fun queueWriteReliable(
c: BluetoothGattCharacteristic,
cont: Continuation<Unit>
) = queueWork("rwriteC ${c.uuid}", cont) {
logAssert(gatt!!.beginReliableWrite())
currentReliableWrite = c.value.clone()
gatt!!.writeCharacteristic(c)
}
/* fun asyncWriteReliable(
c: BluetoothGattCharacteristic,
cb: (Result<Unit>) -> Unit
) = queueWriteCharacteristic(c, CallbackContinuation(cb)) */
fun writeReliable(c: BluetoothGattCharacteristic): Unit =
makeSync { queueWriteReliable(c, it) }
private fun queueWriteDescriptor(
c: BluetoothGattDescriptor,
cont: Continuation<BluetoothGattDescriptor>

Wyświetl plik

@ -145,7 +145,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
// FIXME, instead compare version strings carefully to see if less than
val needsUpdate = (curver != swVer)
return needsUpdate && !isDevBuild
return needsUpdate && !isDevBuild && false // temporarily disabled because it fails occasionally
}
/** Return the filename this device needs to use as an update (or null if no update needed)
@ -199,6 +199,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
info("Starting firmware update for $assetName")
progress = 0
val totalSizeDesc = service.getCharacteristic(SW_UPDATE_TOTALSIZE_CHARACTER)
val dataDesc = service.getCharacteristic(SW_UPDATE_DATA_CHARACTER)
val crc32Desc = service.getCharacteristic(SW_UPDATE_CRC32_CHARACTER)
@ -219,7 +220,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
)
sync.writeCharacteristic(totalSizeDesc)
// Our write completed, queue up a readback
// Our write completed, queue up a readback
val totalSizeReadback = sync.readCharacteristic(totalSizeDesc)
.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0)
if (totalSizeReadback == 0) // FIXME - handle this case
@ -238,8 +239,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
// slightly expensive to keep reallocing this buffer, but whatever
logAssert(firmwareStream.read(buffer) == blockSize)
firmwareCrc.update(buffer)
// updateGatt.beginReliableWrite()
dataDesc.value = buffer
sync.writeCharacteristic(dataDesc)
firmwareNumSent += blockSize

Wyświetl plik

@ -320,6 +320,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
debug("User started firmware update")
updateFirmwareButton.isEnabled = false // Disable until things complete
updateProgressBar.visibility = View.VISIBLE
updateProgressBar.progress = 0 // start from scratch
scanStatusText.text = "Updating firmware, wait up to eight minutes..."
service.startFirmwareUpdate()
@ -342,6 +343,32 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
return inflater.inflate(R.layout.settings_fragment, container, false)
}
private fun initNodeInfo() {
val connected = model.isConnected.value
// If actively connected possibly let the user update firmware
val info = model.myNodeInfo.value
if (connected == MeshService.ConnectionState.CONNECTED && info != null && info.shouldUpdate) {
updateFirmwareButton.visibility = View.VISIBLE
updateFirmwareButton.text =
getString(R.string.update_to).format(getString(R.string.cur_firmware_version))
} else {
updateFirmwareButton.visibility = View.GONE
updateProgressBar.visibility = View.GONE
}
when (connected) {
MeshService.ConnectionState.CONNECTED -> {
val fwStr = info?.firmwareString ?: ""
scanStatusText.text = getString(R.string.connected_to).format(fwStr)
}
MeshService.ConnectionState.DISCONNECTED ->
scanStatusText.text = getString(R.string.not_connected)
MeshService.ConnectionState.DEVICE_SLEEP ->
scanStatusText.text = getString(R.string.connected_sleeping)
}
}
/// Setup the ui widgets unrelated to BLE scanning
private fun initCommonUI() {
model.ownerName.observe(viewLifecycleOwner, Observer { name ->
@ -351,29 +378,12 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
// Only let user edit their name or set software update while connected to a radio
model.isConnected.observe(viewLifecycleOwner, Observer { connected ->
usernameView.isEnabled = connected == MeshService.ConnectionState.CONNECTED
initNodeInfo()
})
// If actively connected possibly let the user update firmware
val info = model.myNodeInfo.value
if (connected == MeshService.ConnectionState.CONNECTED && info != null && info.couldUpdate) {
updateFirmwareButton.visibility = View.VISIBLE
updateFirmwareButton.text =
getString(R.string.update_to).format(getString(R.string.cur_firmware_version))
} else {
updateFirmwareButton.visibility = View.GONE
updateProgressBar.visibility = View.GONE
}
when (connected) {
MeshService.ConnectionState.CONNECTED -> {
val fwStr = info?.firmwareString ?: ""
scanStatusText.text = getString(R.string.connected_to).format(fwStr)
}
MeshService.ConnectionState.DISCONNECTED ->
scanStatusText.text = getString(R.string.not_connected)
MeshService.ConnectionState.DEVICE_SLEEP ->
scanStatusText.text = getString(R.string.connected_sleeping)
}
// Also watch myNodeInfo because it might change later
model.myNodeInfo.observe(viewLifecycleOwner, Observer {
initNodeInfo()
})
updateFirmwareButton.setOnClickListener {

@ -1 +1 @@
Subproject commit b53b7f90b326ef6b1dedca32a2472784e63d10e6
Subproject commit 8ccbd0b688e9ed1e2ccd836414d535f7a6d5366e