feat: ESP MTU 512 + dynamic Android chunk size based on negotiated MTU
This commit is contained in:
parent
475c029512
commit
fcbf1e9b5f
3 changed files with 14 additions and 6 deletions
|
|
@ -59,6 +59,7 @@ class BleRelayManager(
|
||||||
private var otaCharacteristic: BluetoothGattCharacteristic? = null
|
private var otaCharacteristic: BluetoothGattCharacteristic? = null
|
||||||
private var espVersion: String? = null
|
private var espVersion: String? = null
|
||||||
private var appVersion: String = ""
|
private var appVersion: String = ""
|
||||||
|
private var negotiatedMtu: Int = 23
|
||||||
|
|
||||||
interface OtaNotifyCallback {
|
interface OtaNotifyCallback {
|
||||||
fun onOtaNotify(status: Int, seq: Int)
|
fun onOtaNotify(status: Int, seq: Int)
|
||||||
|
|
@ -229,6 +230,8 @@ class BleRelayManager(
|
||||||
|
|
||||||
fun getEspVersion(): String? = espVersion
|
fun getEspVersion(): String? = espVersion
|
||||||
|
|
||||||
|
fun getNegotiatedMtu(): Int = negotiatedMtu
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
private fun connectToDevice(device: android.bluetooth.BluetoothDevice) {
|
private fun connectToDevice(device: android.bluetooth.BluetoothDevice) {
|
||||||
handler.post { callbacks.onStatusChanged(BleStatus.Connecting) }
|
handler.post { callbacks.onStatusChanged(BleStatus.Connecting) }
|
||||||
|
|
@ -274,6 +277,7 @@ class BleRelayManager(
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
override fun onMtuChanged(gatt: android.bluetooth.BluetoothGatt, mtu: Int, status: Int) {
|
override fun onMtuChanged(gatt: android.bluetooth.BluetoothGatt, mtu: Int, status: Int) {
|
||||||
Log.d(TAG, "MTU changed to $mtu")
|
Log.d(TAG, "MTU changed to $mtu")
|
||||||
|
negotiatedMtu = mtu
|
||||||
val service = gatt.getService(SERVICE_UUID)
|
val service = gatt.getService(SERVICE_UUID)
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
relayCharacteristic = service.getCharacteristic(CHARACTERISTIC_UUID)
|
relayCharacteristic = service.getCharacteristic(CHARACTERISTIC_UUID)
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,12 @@ class OtaManager(
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "OtaManager"
|
private const val TAG = "OtaManager"
|
||||||
private const val OTA_CHUNK_DATA_SIZE = 248
|
|
||||||
private const val OTA_CMD_START: Byte = 0x10
|
private const val OTA_CMD_START: Byte = 0x10
|
||||||
private const val OTA_STATUS_ACK: Byte = 0x00
|
|
||||||
private const val OTA_STATUS_COMPLETE: Byte = 0x10
|
|
||||||
private const val OTA_STATUS_ERROR: Byte = 0x11
|
|
||||||
private const val OTA_START_TIMEOUT_MS = 10000L
|
private const val OTA_START_TIMEOUT_MS = 10000L
|
||||||
private const val OTA_CHUNK_TIMEOUT_MS = 2000L
|
private const val OTA_CHUNK_TIMEOUT_MS = 2000L
|
||||||
private const val OTA_FINAL_TIMEOUT_MS = 10000L
|
private const val OTA_FINAL_TIMEOUT_MS = 10000L
|
||||||
private const val MAX_RETRIES = 3
|
private const val MAX_RETRIES = 3
|
||||||
|
private const val OTA_ESP_MAX_CHUNK = 500
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OtaCallback {
|
interface OtaCallback {
|
||||||
|
|
@ -36,10 +33,16 @@ class OtaManager(
|
||||||
}
|
}
|
||||||
|
|
||||||
private var firmwareData: ByteArray? = null
|
private var firmwareData: ByteArray? = null
|
||||||
|
private var chunkDataSize: Int = 248
|
||||||
|
|
||||||
|
private fun calculateChunkSize(mtu: Int): Int {
|
||||||
|
return minOf(maxOf(mtu - 3 - 4, 20), OTA_ESP_MAX_CHUNK)
|
||||||
|
}
|
||||||
|
|
||||||
fun loadFirmware(): Boolean {
|
fun loadFirmware(): Boolean {
|
||||||
return try {
|
return try {
|
||||||
firmwareData = context.assets.open("firmware/firmware.bin").readBytes()
|
firmwareData = context.assets.open("firmware/firmware.bin").readBytes()
|
||||||
|
chunkDataSize = calculateChunkSize(relayManager.getNegotiatedMtu())
|
||||||
true
|
true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Failed to load firmware", e)
|
Log.e(TAG, "Failed to load firmware", e)
|
||||||
|
|
@ -85,13 +88,13 @@ class OtaManager(
|
||||||
}
|
}
|
||||||
} catch (_: kotlinx.coroutines.TimeoutCancellationException) {}
|
} catch (_: kotlinx.coroutines.TimeoutCancellationException) {}
|
||||||
|
|
||||||
val totalChunks = (fw.size + OTA_CHUNK_DATA_SIZE - 1) / OTA_CHUNK_DATA_SIZE
|
val totalChunks = (fw.size + chunkDataSize - 1) / chunkDataSize
|
||||||
var seq = 0
|
var seq = 0
|
||||||
var offset = 0
|
var offset = 0
|
||||||
|
|
||||||
while (offset < fw.size) {
|
while (offset < fw.size) {
|
||||||
val remaining = fw.size - offset
|
val remaining = fw.size - offset
|
||||||
val chunkSize = minOf(remaining, OTA_CHUNK_DATA_SIZE)
|
val chunkSize = minOf(remaining, chunkDataSize)
|
||||||
|
|
||||||
val packet = ByteBuffer.allocate(4 + chunkSize).order(ByteOrder.BIG_ENDIAN)
|
val packet = ByteBuffer.allocate(4 + chunkSize).order(ByteOrder.BIG_ENDIAN)
|
||||||
packet.putInt(seq)
|
packet.putInt(seq)
|
||||||
|
|
|
||||||
|
|
@ -338,6 +338,7 @@ void setup() {
|
||||||
}
|
}
|
||||||
Serial.println("LED blink done, starting BLE...");
|
Serial.println("LED blink done, starting BLE...");
|
||||||
|
|
||||||
|
NimBLEDevice::setMTU(512);
|
||||||
NimBLEDevice::init("SylDa_Server");
|
NimBLEDevice::init("SylDa_Server");
|
||||||
|
|
||||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue