3

我有一個定製的硬件與藍牙低能量芯片。我已經用500 u32s的數組設置它,例如array [n] == n。我正在研究一個可連接到設備的android應用程序,請求數組的長度,然後一次請求數組中的數據點。onCharacteristicWrite()被調用,但它並不總是寫

Android應用似乎大多工作正常。它連接到設備,請求長度,並在收到上一部分後繼續請求下一條數據。然而,在數組中的任何部分(任何地方有2到450個元素 - 看起來不一致),它會寫入另一個命令,並且它會一直到onCharacteristicWrite(),但它永遠不會收到響應。我將我的BLE外設連接到CoolTerm,並且它甚至從未收到該命令。下面是我的代碼片段和原木:

BLEService:

private final BluetoothGattCallback bleGattCallback = new BluetoothGattCallback() { 

    @Override 
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 
     super.onCharacteristicRead(gatt, characteristic, status); 
     Log.d("onCharacteristicRead", byteArrToHex(characteristic.getValue())); 
    } 

    @Override 
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 
     if(status != BluetoothGatt.GATT_SUCCESS){ 
      Log.d("onCharacteristicWrite", "Failed write, retrying"); 
      gatt.writeCharacteristic(characteristic); 
     } 
     Log.d("onCharacteristicWrite", byteArrToHex(characteristic.getValue())); 
     super.onCharacteristicWrite(gatt, characteristic, status); 
    } 

    @Override 
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { 
     super.onCharacteristicChanged(gatt, characteristic); 
     Log.d("onCharacteristicChanged", byteArrToHex(characteristic.getValue())); 
     broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); 
    } 

}; 

我省略了相關描述回調的不必要的部分寫道,連接狀態的變化,等等。當數據被廣播,它接收MainActivity的這一部分:

private BroadcastReceiver messageReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     String receivedUUID = intent.getStringExtra("uuid"); 
     byte[] data = intent.getByteArrayExtra("data"); 
     Log.d("messageReceiver", "received intent in mainActivity with uuid " + receivedUUID.toString()); 
     if(receivedUUID.equals(READ_LEN_UUID.toString()) && currentlyReading) { 
      datapoints = new ArrayList<Long>(); 
      numberOfDatapoints = 0; 
      numberOfDatapoints |= (data[0] & 0xff); 
      numberOfDatapoints |= (data[1] & 0xff) << 8; 
      numberOfDatapoints |= (data[2] & 0xff) << 16; 
      numberOfDatapoints |= (data[3] & 0xff) << 24; 
      Log.d("RECEIVER TEST:", "number of datapoints = " + numberOfDatapoints); 

      if(numberOfDatapoints > 0) { 
       bleService.requestDatapoint(0); 
      } 
     } else if (receivedUUID.equals(READ_DATAPOINT_UUID.toString()) && currentlyReading){ 
      long message = 0; 
      message |= (data[0] & 0xff); 
      message |= (data[1] & 0xff) << 8; 
      message |= (data[2] & 0xff) << 16; 
      message |= (data[3] & 0xff) << 24; 

      Log.d("Datapoint Recieved", "Index " + datapoints.size() + " = " + message); 
      datapoints.add(message); 

      if(datapoints.size() < numberOfDatapoints){ 
       bleService.requestDatapoint(datapoints.size()); 
      } 
     } 
    } 
}; 

的代碼調用writeCharacteristic:

public void requestDatapoint(int index){ 
    Log.d("requestDatapoint", "Requested datapoint at " + index); 

    BluetoothGattCharacteristic commandChar = this.gattService.getCharacteristic(WRITE_UUID); 
    byte[] request = new byte[3]; 

    // command - 2 = get index 
    request[0] = (byte) (2 & 0xff); 

    // index 
    request[1] = (byte) ((index) & 0xff); 
    request[2] = (byte) ((index >> 8) & 0xff); 
    commandChar.setValue(request); 
    bleGatt.writeCharacteristic(commandChar); 
} 

我很確定發送命令太快沒有問題。這實際上非常慢,我故意這樣做,以便在進入項目的下一部分之前,我可以更輕鬆地進行測試。

08-23 12:08:18.470 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 49 
08-23 12:08:18.570 16753-16765/sethp.datalogcollector D/onCharacteristicWrite: 02 31 00 
08-23 12:08:18.570 16753-16765/sethp.datalogcollector D/onCharacteristicChanged: 31 00 00 00 
08-23 12:08:18.570 16753-16765/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241 
08-23 12:08:18.575 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241 
08-23 12:08:18.575 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 49 = 49 
08-23 12:08:18.575 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 50 
08-23 12:05:55.585 16753-16765/sethp.datalogcollector D/onCharacteristicWrite: 02 32 00 
08-23 12:05:55.585 16753-16765/sethp.datalogcollector D/onCharacteristicChanged: 32 00 00 00 
08-23 12:05:55.585 16753-16765/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241 
08-23 12:05:55.585 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241 
08-23 12:05:55.590 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 50 = 50 
08-23 12:05:55.590 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 51 
08-23 12:05:55.680 16753-16845/sethp.datalogcollector D/onCharacteristicWrite: 02 33 00 
08-23 12:05:55.685 16753-16764/sethp.datalogcollector D/onCharacteristicChanged: 33 00 00 00 
08-23 12:05:55.685 16753-16764/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241 
08-23 12:05:55.685 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241 
08-23 12:05:55.685 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 51 = 51 
08-23 12:05:55.685 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 52 
08-23 12:05:55.785 16753-16765/sethp.datalogcollector D/onCharacteristicChanged: 34 00 00 00 
08-23 12:05:55.785 16753-16765/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241 
08-23 12:05:55.785 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241 
08-23 12:05:55.785 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 52 = 52 
08-23 12:05:55.785 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 53 
08-23 12:05:55.790 16753-16765/sethp.datalogcollector D/onCharacteristicWrite: 02 35 00 

和我的相應CoolTerm日誌摘錄:

command: 02 
index: 0031 
command = 2 
datapoint at 49 = 49 
attempting to send 49 

command: 02 
index: 0032 
command = 2 
datapoint at 50 = 50 
attempting to send 50 

command: 02 
index: 0033 
command = 2 
datapoint at 51 = 51 
attempting to send 51 

command: 02 
index: 0034 
command = 2 
datapoint at 52 = 52 
attempting to send 52 

注意,在我的周圍的日誌,它不會出現接收請求從我的調試日誌,一個

的片斷for datapoint 53. 作爲參考,onCharacteristicWrite調試中的第一個十六進制字節是命令。命令02只是意味着我正在請求一個數據點在下一個2字節包含的索引處。

我注意到,在Android日誌中,沒有用於請求數據點51的onCharacteristicWrite日誌。這似乎每次都發生在它停止獲取數據之前,但我不確定這是否顯着或如果這只是日誌緩衝區的問題。

我已經運行了很多測試,試圖注意到任何模式,並且我注意到,當設備沒有連接到調試電纜時,它似乎獲得了更多的數據點。我現在唯一的想法是,也許我有一個異步中斷回調的問題,但我不知道會做什麼。有沒有人想過爲什麼在調用onCharacteristicWrite之後似乎沒有真正寫入數據?

感謝

編輯:

我跟着埃米爾的建議,並開啓藍牙記錄。我用wireshark玩弄了一下,弄清楚發生了什麼事情。我再次嘗試了我的應用程序,然後運行到索引102,直到它停止,此時我斷開了設備連接。我在Wireshark中挖掘了數據包,發現我的設備DID收到了大約102的數據,但它沒有發送103的請求。我仔細檢查了我的android日誌,並從onCharacteristicWrite內部的一條Log語句表示它發送了命令02 67 00,這是對103的請求。所以,看起來onCharacteristicWrite被調用,但實際上並沒有寫入該特性。

經過一番更多的盯着和思考之後,我很確定1)onCharacteristicWrite被錯誤地調用,因爲數據永遠不會被寫入,或者2)某種程度上異步的中斷會阻止它傳輸。我不知道這樣做會是什麼。

最後編輯:

即使這樣,據我從規範理解,onCharacteristicWrite只應該被稱爲當一個可靠的,成功寫入過程中,我決定檢查從writeCharacteristic的返回值。我應該在幾個小時前檢查。你知道什麼,它是在最後一次請求時返回錯誤的。

我認爲onCharacteristicWrite被調用即使返回值爲false也是一個錯誤。我讀過使用onCharacteristicWrite調用寫入下一塊數據是安全的。要麼他們錯了,要麼就是在這裏發生一些棘手的事情。無論哪種方式,我想這是一個非常好的主意,檢查這些函數調用返回值。

+0

你可以顯示實際調用writeCharacteristic的代碼嗎? – Emil

+0

當然,現在加入它 – Seth

+0

嗯,這似乎很奇怪。您是否使用https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#WRITE_TYPE_NO_RESPONSE?此外,您可以嘗試啓用bluetooth hci snoop日誌,然後在Wireshark中檢查它以查看無線發送的內容。 – Emil

回答

1

現在我想我明白了。有時通知在onWriteCharacteristic回調之前到達。由於您在通知回調中發出下一次寫入,所以前一次寫入仍處於掛起狀態。在發出下一次寫入之前,必須確保已調用onWriteCharacteristic。

+0

你確定嗎?例如,如果我想要數據點7,我會寫這個請求,然後onCharacteristicWrite會在它正在寫入成功時被調用,然後onCharacterisicChanged被調用,當我得到一個響應時,我會請求數據點8.是否可能onCharacteristicWrite在獲得響應之前甚至沒有被調用? – Seth

+0

是的,onCharacteristicWrite將在外設發回GATT寫入響應時調用。由於它同時發回了一個通知,我想它是未定義的,它首先傳遞給你的應用程序。在您的logcat日誌中,最後一次寫入響應在通知後與之前的數據包進行比較。由於characteristic.getValue()包含寫入或通知的最後一個值,因此您認爲這是對未發送寫入的響應(請記住,您自己設置特徵值)。無論如何,看看你的snooplog訂單是通過空中發送的。 – Emil

+0

嗯,是的,這真的很有趣。雖然有意義。感謝您幫我解決這個問題! +1 – Seth

相關問題