Android BLE 回调onCharacteristicWrite 时 返回的status 偶尔是失败的原因

首先,只有setType是writeWithResponse的时候,才会触发onCharacteristicWrite回调,这是GATT协议层的响应机制。writeWithoutResponse由于不需要外设端在GATT层以上做响应,所以是不会触发这个回调的。

根据BLE协议,射频链路层的重发机制对于ATT层和GATT层都是黑盒。链路层的重试机制一定会保证数据包以发送的顺序在对端被接收,如果数据发送失败则会无限次重试,直到发送成功或连接超时才会停止。不管是没有接收到射频信号或接收到了数据但CRC校验错误都算失败,区别是没有接收到射频信号会累加连接超时的计数器。

也就是说链路层的数据只存在发送成功(可能经过重发N次后成功),或者连接断开,不存在失败的可能性,也就无所谓返回status状态的意义。

onCharacteristicWrite返回的status状态看一下API就知道了,都是GATT开头的各种常量,也就是说从设备一定是接收到了数据,但是数据从链路层转发到GATT层的过程中可能存在各种异常情况,导致返回错误。需要注意的是应用层无法决定这个返回状态,比如说如果从设备的应用层接收到数据后发现不符合自己定义的接口数据协议规范,那么也只能通过另外发起notify来通知主设备,而无法通过status来返回错误类型。

也就是说,status的真正意义是告诉主设备,写入的信息是否已经被从设备的GATT层接收到并触发应用层回调函数,仅此而已,这里失败的话是需要主设备的应用层来决定是否进行重发的,但与链路层无关,失败的原因也不是所谓的链路层丢包。

附带提一下,writeCharacteristic的返回值代表Android的app是否把数据成功送达到手机的蓝牙芯片的数据缓冲区中,由于手机端蓝牙数据流控机制的存在,且手机上的蓝牙物理组成通常是芯片只包含控制器这一层的射频和链路部分,作为主机的上位机通常是由手机系统的硬件充当,所以这里返回true也很可能是命令还在主机流控队列中排队,而不是真正的通过手机蓝牙射频信号发射出去,所以这个返回值几乎不可能是false,也没什么意义,实际上iOS系统下的对等函数就没有这个返回值。

附带一下status的错误码,其实API里就能看到的。

GATT_ILLEGAL_PARAMETER 0x0087 (135)

GATT_NO_RESOURCES 0x0080 (128)

GATT_INTERNAL_ERROR 0x0081 (129)

GATT_WRONG_STATE 0x0082 (130)

GATT_DB_FULL 0x0083 (131)

GATT_BUSY 0x0084 (132)

GATT_ERROR 0x0085 (133)

GATT_CMD_STARTED 0x0086 (134)

GATT_PENDING 0x0088 (136)

GATT_AUTH_FAIL 0x0089 (137)

GATT_MORE 0x008a (138)

GATT_INVALID_CFG 0x008b (139)

GATT_SERVICE_STARTED 0x008c (140)

GATT_ENCRYPED_MITM

GATT_SUCCESS

GATT_ENCRYPED_NO_MITM 0x008d (141)

GATT_NOT_ENCRYPTED 0x008e (142)

你可能感兴趣的:(Android BLE 回调onCharacteristicWrite 时 返回的status 偶尔是失败的原因)