1、遇到的问题

公司要经过Android设备给外围设备的固件进行OTA晋级,最开端想到的有两种计划。

1、将当前Android设备所衔接 Wifi称号,WiFi密码经过BLE发送给外围设备。 外围设备拿到当前环境的WiFi称号和密码衔接热点, 然后自己去服务器下载OTA文件,进行晋级
2、当前Android设备和外围设备经过经典蓝牙进行传输OTA文件, 外围设备拿到OTA文件进行晋级

可是很惋惜,外围设备既没有WiFi芯片, 也没有经典蓝牙芯片, 只有一颗BLE(低功耗蓝牙)芯片。 这意味着上面的两种计划都行不通。 那咱们能不能经过BLE芯片来做文章, 来传输OTA文件?

BLE规划之初就是为了传输简单的指令的, 传输一些小数据的, 每次发送的数据巨细不能超越20个字节。到底靠不靠谱啊?

2、 能不能经过BLE传输文件

让咱们来问问 GPT 吧

Android通过BLE传输文件

GPT 的回答, 是能够经过BLE传输文件的, 因为BLE 每次传输的内容最大为20个字节, 传输大文件时就需求分包传输, 一起需求确保分包传输的可靠性和稳定性。

3、 怎么传输文件

让 GPT 给咱们一些示例代码

Android通过BLE传输文件

能够看出, 发送端分包批量发送数据,接纳端

4、怎么确保可靠性和稳定性

Android通过BLE传输文件

1、超时重传

蓝牙在传输过程中, 或许会存在丢包的状况。分两种状况, 1、Android设备发送的数据,外设设备没有收到。 2、Android设备发送的数据,外设设备收到了,而且发送了回复承认。 回复承认包Android设备却没有收到。

呈现了这两种状况的任意一种, 则以为发生了丢包的状况。 Android 对这个包进行重发。

2、序列号

针对超时重传的第二种状况, 外设设备会收到两个相同的包。 可是外设设备不清楚是不是重装包。 这时就要给每个数据包增加序列号。 等外设设备收到两个相同序列号的数据包时, 丢弃这个数据包, 回复Android设备收到此包, 开端发送下一个数据包。

3、数据校验

BLE在传输的过程中, 如果周围环境有强蓝牙搅扰,或者其他传输通道, 或许会导致数据包变更, 所以需求在数据包增加一个校验位, 这个校验位根据特定的算法,由数据包的数据核算得来。 外设设备收到数据后, 从头核算校验位, 判断数据传输过程是否呈现差错, 如果核算的校验位和包传输的校验位不一致, 则要求Android设备从头发送这个包。

5、 传输速度提高 RequestMtu

为了确保传输过程中的可靠性和稳定性,咱们需求在传输包中,增加序列号,数据校验等信息。 Android默许每个BLE数据包不超越20个字节,当咱们加了一些其他信息时, 每次传输的有效数据或许只有15个字节左右。 导致在传输的过程中分包更多, 传输时刻更长。

为了提高传输的速度, 咱们来提高BLE每个数据包的传输巨细约束, 使每个分包能够传输更多的数据。 体系为咱们供给了 RequestMtu这个接口。 需求在gatt衔接成功时调用

    private val bluetoothGattCallback = object : BluetoothGattCallback() {
        override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
            super.onConnectionStateChange(gatt, status, newState)
            if (newState == BluetoothGatt.STATE_CONNECTED) {
                Log.d(TAG, "gatt  衔接成功")
                gatt?.requestMtu(40)
            } else {
                Log.d(TAG, "gatt  衔接失利 status $status  newstate $newState")
            }
        }
        override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
            super.onMtuChanged(gatt, mtu, status)
            if (BluetoothGatt.GATT_SUCCESS == status) {
                Log.d(TAG, "onMtuChanged suc : $mtu")
                gatt?.discoverServices()
            } else {
                Log.d(TAG, "onMtuChanged fail : $status")
            }
        }
    }

MTU改动成功后, 再去gatt.discoverServices()发现服务

参阅:

www.jianshu.com/p/743dd0b42…

eleaction01.spaces.eepw.com.cn/articles/ar…