mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-03-29 19:23:30 -04:00
Fix back to back writes to not overwrite BLE characterstic. Fixes
the "sending while device was asleep bug"
This commit is contained in:
@@ -217,9 +217,8 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String
|
||||
// Note: we generate a new characteristic each time, because we are about to
|
||||
// change the data and we want the data stored in the closure
|
||||
val toRadio = getCharacteristic(uuid)
|
||||
toRadio.value = a
|
||||
|
||||
s.asyncWriteCharacteristic(toRadio) { r ->
|
||||
s.asyncWriteCharacteristic(toRadio, a) { r ->
|
||||
try {
|
||||
r.getOrThrow()
|
||||
debug("write of ${a.size} bytes completed")
|
||||
|
||||
@@ -622,19 +622,25 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
||||
|
||||
private fun queueWriteCharacteristic(
|
||||
c: BluetoothGattCharacteristic,
|
||||
v: ByteArray,
|
||||
cont: Continuation<BluetoothGattCharacteristic>
|
||||
) = queueWork("writeC ${c.uuid}", cont) {
|
||||
currentReliableWrite = null
|
||||
c.value = v
|
||||
gatt!!.writeCharacteristic(c)
|
||||
}
|
||||
|
||||
fun asyncWriteCharacteristic(
|
||||
c: BluetoothGattCharacteristic,
|
||||
v: ByteArray,
|
||||
cb: (Result<BluetoothGattCharacteristic>) -> Unit
|
||||
) = queueWriteCharacteristic(c, CallbackContinuation(cb))
|
||||
) = queueWriteCharacteristic(c, v, CallbackContinuation(cb))
|
||||
|
||||
fun writeCharacteristic(c: BluetoothGattCharacteristic): BluetoothGattCharacteristic =
|
||||
makeSync { queueWriteCharacteristic(c, it) }
|
||||
fun writeCharacteristic(
|
||||
c: BluetoothGattCharacteristic,
|
||||
v: ByteArray
|
||||
): BluetoothGattCharacteristic =
|
||||
makeSync { queueWriteCharacteristic(c, v, it) }
|
||||
|
||||
/** Like write, but we use the extra reliable flow documented here:
|
||||
* https://stackoverflow.com/questions/24485536/what-is-reliable-write-in-ble
|
||||
|
||||
@@ -13,6 +13,48 @@ import com.geeksville.util.exceptionReporter
|
||||
import java.util.*
|
||||
import java.util.zip.CRC32
|
||||
|
||||
/**
|
||||
* Move this somewhere as a generic network byte order function
|
||||
*/
|
||||
fun toNetworkByteArray(value: Int, formatType: Int): ByteArray {
|
||||
|
||||
val len: Int = 4 // getTypeLen(formatType)
|
||||
val mValue = ByteArray(len)
|
||||
|
||||
when (formatType) {
|
||||
/* BluetoothGattCharacteristic.FORMAT_SINT8 -> {
|
||||
value = intToSignedBits(value, 8)
|
||||
mValue.get(offset) = (value and 0xFF).toByte()
|
||||
}
|
||||
BluetoothGattCharacteristic.FORMAT_UINT8 -> mValue.get(offset) =
|
||||
(value and 0xFF).toByte()
|
||||
BluetoothGattCharacteristic.FORMAT_SINT16 -> {
|
||||
value = intToSignedBits(value, 16)
|
||||
mValue.get(offset++) = (value and 0xFF).toByte()
|
||||
mValue.get(offset) = (value shr 8 and 0xFF).toByte()
|
||||
}
|
||||
BluetoothGattCharacteristic.FORMAT_UINT16 -> {
|
||||
mValue.get(offset++) = (value and 0xFF).toByte()
|
||||
mValue.get(offset) = (value shr 8 and 0xFF).toByte()
|
||||
}
|
||||
BluetoothGattCharacteristic.FORMAT_SINT32 -> {
|
||||
value = intToSignedBits(value, 32)
|
||||
mValue.get(offset++) = (value and 0xFF).toByte()
|
||||
mValue.get(offset++) = (value shr 8 and 0xFF).toByte()
|
||||
mValue.get(offset++) = (value shr 16 and 0xFF).toByte()
|
||||
mValue.get(offset) = (value shr 24 and 0xFF).toByte()
|
||||
} */
|
||||
BluetoothGattCharacteristic.FORMAT_UINT32 -> {
|
||||
mValue[0] = (value and 0xFF).toByte()
|
||||
mValue[1] = (value shr 8 and 0xFF).toByte()
|
||||
mValue[2] = (value shr 16 and 0xFF).toByte()
|
||||
mValue[3] = (value shr 24 and 0xFF).toByte()
|
||||
}
|
||||
else -> TODO()
|
||||
}
|
||||
return mValue
|
||||
}
|
||||
|
||||
/**
|
||||
* typical flow
|
||||
*
|
||||
@@ -211,14 +253,10 @@ class SoftwareUpdateService : JobIntentService(), Logging {
|
||||
val firmwareSize = firmwareStream.available()
|
||||
|
||||
// Start the update by writing the # of bytes in the image
|
||||
logAssert(
|
||||
totalSizeDesc.setValue(
|
||||
firmwareSize,
|
||||
BluetoothGattCharacteristic.FORMAT_UINT32,
|
||||
0
|
||||
)
|
||||
sync.writeCharacteristic(
|
||||
totalSizeDesc,
|
||||
toNetworkByteArray(firmwareSize, BluetoothGattCharacteristic.FORMAT_UINT32)
|
||||
)
|
||||
sync.writeCharacteristic(totalSizeDesc)
|
||||
|
||||
// Our write completed, queue up a readback
|
||||
val totalSizeReadback = sync.readCharacteristic(totalSizeDesc)
|
||||
@@ -239,23 +277,18 @@ class SoftwareUpdateService : JobIntentService(), Logging {
|
||||
// slightly expensive to keep reallocing this buffer, but whatever
|
||||
logAssert(firmwareStream.read(buffer) == blockSize)
|
||||
firmwareCrc.update(buffer)
|
||||
|
||||
dataDesc.value = buffer
|
||||
sync.writeCharacteristic(dataDesc)
|
||||
|
||||
sync.writeCharacteristic(dataDesc, buffer)
|
||||
firmwareNumSent += blockSize
|
||||
}
|
||||
|
||||
// We have finished sending all our blocks, so post the CRC so our state machine can advance
|
||||
val c = firmwareCrc.value
|
||||
info("Sent all blocks, crc is $c")
|
||||
logAssert(
|
||||
crc32Desc.setValue(
|
||||
c.toInt(),
|
||||
BluetoothGattCharacteristic.FORMAT_UINT32,
|
||||
0
|
||||
)
|
||||
sync.writeCharacteristic(
|
||||
crc32Desc,
|
||||
toNetworkByteArray(c.toInt(), BluetoothGattCharacteristic.FORMAT_UINT32)
|
||||
)
|
||||
sync.writeCharacteristic(crc32Desc)
|
||||
|
||||
// we just read the update result if !0 we have an error
|
||||
val updateResult =
|
||||
|
||||
Reference in New Issue
Block a user