2017-06-16 133 views
0

我试图通过BLE在android和其他arm设备之间交换一些数据,并且大数据由于MTU的限制而被分割成小片段。为了鲁棒性,当其前一帧已被确认时(onCharacteristicWrite),只能发送一帧(由writeCharacteristic)。现在这里出现的问题:当Android设备完成发送最后一帧,然后从对端设备接收数据(由onCharacteristicChanged),它接缝onCharacteristicWrite迟于onCharacteristicChanged(至少日志说),这里是我的代码。为什么onCharacteristicWrite()比BLE通信中的onCharacteristicChanged()迟来

@Override 
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 
    if (status != BluetoothGatt.GATT_SUCCESS) { 
     stateProcessError();     // State = STATE_IDLE 
     return;        // Log.v("error occurs", "do something"); 
    } 
    Log.v("didsend", "State:" + State); 
    processEvent(sp_event.DATA_SEND_CFM, null); 
} 

@Override 
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { 
    Log.v("didrecv", "State:" + State); 
    Object msg = constructRxMsg(characteristic.getValue()); 
    processEvent(sp_event.DATA_RECV_CFM, msg); 
} 

private void stateSendAuthReq(sp_event event) { 
    switch (event) { 
     case DATA_IDLE: { 
      SPTxMsgAuthReq msg = new SPTxMsgAuthReq(Mode); 
      sendData(msg.getMsg()); 
     } 
      break; 
     case DATA_SEND_CFM: 
      State = sp_state.STATE_RECV_AUTH_RES; 
      Log.v("sendReq", "change State"); 
      break; 
     default: 
      Log.v("sendReq", "default"); 
      this.stateProcessError(); 
      break; 
    } 
} 

private void stateRecvAuthRes(sp_event event, SPRxMsgAuthRes msg) { 
    if (sp_event.DATA_RECV_CFM != event || null == msg) { 
     this.stateProcessError(); 
     return; 
    } 
    if (MSG_TYPE_AUTH_RES != msg.getType() || STATUS_AUTH_READY != msg.getStatus()) { 
     Log.v("recvAuthRes", "incorrect param"); 
     this.stateProcessError(); 
     return; 
    }     
    State = sp_state.STATE_RECV_NONCE; 
} 

private void processEvent(sp_event event, Object msg) { 
    switch (State) { 
     case STATE_IDLE: 
      this.stateSendAuthReq(event) 
      break; 
     case STATE_RECV_AUTH_RES: 
      this.stateRecvAuthRes(event, (SPRxMsgAuthRes) msg); 
      break; 
     ...... 
    } 
} 

日志显示的问题,因为这样的:

06-16 17:32:46.521 10300-10412/alps.ble.bt V/send: data:[-32, 3, 3, 1, 0] 
06-16 17:32:46.621 10300-10406/alps.ble.bt V/didrecv: State:STATE_IDEL 
06-16 17:32:46.621 10300-10406/alps.ble.bt V/constructRxMsg: data:[-31, 2, 3, 0] 
06-16 17:32:46.621 10300-10406/alps.ble.bt V/error occurs: do something 
06-16 17:32:46.621 10300-10406/alps.ble.bt V/didsend: State:STATE_IDLE 

而旁边是记录时没有错误:

06-16 16:30:05.871 22401-22502/alps.ble.bt V/send: data:[-32, 3, 3, 1, 0] 
06-16 16:30:05.911 22401-22471/alps.ble.bt D/BluetoothGatt: onClientConnParamsChanged() - Device=68:68:28:40:12:8E interval=39 status=0 
06-16 16:30:05.961 22401-22413/alps.ble.bt V/didsend: State:STATE_IDLE 
06-16 16:30:05.961 22401-22413/alps.ble.bt V/didrecv: State:STATE_RECV_AUTH_RES 
06-16 16:30:05.961 22401-22413/alps.ble.bt V/constructRxMsg: data:[-31, 2, 3, 0] 

注意:在对等设备的代码应该是正确的,因为一切正常当我在iOS上测试而不是android。

我希望有足够的信息提供,任何帮助将不胜感激,谢谢!

+0

您确定外设在通知之前发送了写入响应吗?您可以通过使用BLE嗅探器硬件或检查您可以在Android中启用的HCI监听日志来验证此情况,然后使用Wireshark进行查看。这个订单对你真的很重要吗?难道你不能重写你的代码,所以它可以工作吗? – Emil

+0

是的,我检查了这个问题,使用前线BPA600和airlog显示顺序是正确的,所以在我看来也许在我的使用或设置有问题。代码中的状态更改取决于这两个函数,但是您可以重写它以避免此问题。无论如何,我会检查它,最后谢谢你:) – shinyathena

回答

0

这么多尝试后,问题仍然存在,我别无选择,只能避免它像使用缓冲区和标志,我愿意分享它。

private boolean isSending = false; 
private byte[] lastRecvData = null; 

private void sendData(byte[] data) { 
    Log.v("1", "Send data ..."); 
    mCharacteristic.setValue(data); 
    mBluetoothGatt.writeCharacteristic(mCharacteristic) 
    isSending = true; 
} 

@Override 
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 
    isSending = false; 
    if (status != BluetoothGatt.GATT_SUCCESS) { 
     return; 
    } 
    Log.v("2", "Send data successfully"); 
    processEvent(sp_event.DATA_SEND_CFM, null); 

    if (lastRecvData != null) { 
     Object msg = constructRxMsg(lastRecvData); 
     processEvent(sp_event.DATA_RECV_CFM, msg); 
     lastRecvData = null; 
    } 
} 

@Override 
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { 
    if (isSending) { 
     lastRecvData = characteristic.getValue().clone(); 
    }else { 
     Log.v("3", "Recv data"); 
     Object msg = constructRxMsg(characteristic.getValue()); 
     processEvent(sp_event.DATA_RECV_CFM, msg); 
    } 
} 

对于重新连接的情况,应该清除缓冲区和标志。

public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { 
    if (newState == BluetoothProfile.STATE_CONNECTED) { 
     isSending = false; 
     lastRecvData = null; 
     ...... 

如果有人对此问题有更好的想法或解决方案,最后感谢您,我们将不胜感激。

相关问题