3

블루투스 저에너지 칩을 사용하는 맞춤 하드웨어가 있습니다. 나는 array [n] == n과 같은 500 u32s를 가진 배열로 설정했다. 디바이스에 연결하고 배열의 길이를 요청한 다음 어레이의 데이터 포인트를 한 번에 하나씩 요청할 수있는 안드로이드 응용 프로그램에서 작업하고 있습니다.onCharacteristicWrite()가 호출되고 있지만 항상 쓰기는하지 않습니다.

Android 앱이 대부분 정상적으로 작동하는 것으로 보입니다. 장치에 연결하고 길이를 요청한 다음 이전 조각을받은 후 다음 데이터 조각을 계속 요청합니다. 그러나 배열을 통해 (어디에서나 2 ~ 450 개의 요소가 일관성이없는 것처럼 보임) 다른 명령을 작성하고 onCharacteristicWrite() 에까지 도달하게하지만 응답을받지 못합니다. 내 BLE 주변 장치를 CoolTerm에 연결하고 명령을 수신하지도 않습니다. 데이터가 방송되면,이 수신되는 등 I는 기술자와 관련된 콜백의 불필요한 부분을 생략 한

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); 
    } 

}; 

기록한 접속 상태 변화 :

BLEService은 : 여기 내 코드의 단편 및 로그는 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 

내 디버그 로그 중 하나에서 니펫을 데이터 포인트 53. 참고로 onCharacteristicWrite 디버그의 첫 번째 16 진수 바이트가 명령입니다. 커맨드 02는 다음 2 바이트가 포함 된 인덱스의 데이터 포인트를 요청한다는 것을 의미합니다.

안드로이드 로그에서 데이터 포인트 51을 요청하는 onCharacteristicWrite 로그가 없다는 것을 알았습니다. 데이터를 가져 오는 것을 멈추기 직전마다 발생하는 것처럼 보입니다. 그러나 이것이 중요한지 확실하지 않습니다. 로그 버퍼의 문제 일뿐입니다.

나는 패턴을 알아 내려고 몇 가지 테스트를 해봤는데, 장치가 디버그 케이블에 연결되어 있지 않을 때 더 많은 데이터 포인트를 얻는 것으로 나타났습니다. 이 시점에서 내 유일한 생각은 아마도 콜백을 방해하는 비동기식 문제가있을 수 있지만 그 일을하는 것이 무엇인지 모릅니다. 아무도 onCharacteristicWrite가 호출 된 후 실제로 데이터를 쓰지 않는 이유에 대한 의견이 있습니까?

감사

편집 :

내가 에밀의 제안을 따라 블루투스 로깅을 돌았 다. 나는 wireshark로 놀아서 무슨 일이 일어나고 있는지 알아 냈다. 나는 내 앱을 다시 시험해 보았고, 멈출 때까지 인덱스 102까지 달렸다. 그 시점에서 나는 장치를 연결 해제했다. Wireshark의 패킷을 파고 내 장치가 102에 대한 데이터를 수신했지만 103에 대한 요청을 보내지 않았 음을 알았습니다.내 안드로이드 로그를 두 번 확인하고 onCharacteristicWrite 내부의 Log 문은 103에 대한 요청 인 02 67 00 명령을 보냈다 고합니다. 따라서 onCharacteristicWrite가 호출되고 있지만 특성이 실제로 쓰여지고있는 것은 아닙니다.

좀 더 꼼짝 못하고 생각한 후에도 데이터가 결코 쓰여지지 않기 때문에 1) onCharacteristicWrite가 부적절하게 호출되거나 2) 어떻게 든 비동기식으로 인해 전송이 중단되고 전송이 중지되는 것이 확실합니다. 나는 이것을 어떻게 할 것인지 전혀 모른다.

최종 편집은 :

비록, 지금까지의 내가 사양에서 이해, onCharacteristicWrite 만 예정이다

는 신뢰할 수있는, 성공적인 쓰기가 진행 중일 때, 나는 writeCharacteristic의 반환 값을 확인하기로 결정이라고합니다. 몇 시간 전에 확인 했어야했는데. 그리고 당신은 무엇을 알고 있습니다, 그것은 마지막 요청에 거짓으로 돌아가고있었습니다.

반환 값이 false 임에도 불구하고 onCharacteristicWrite가 호출되었다고 생각합니다. 버그입니다. onCharacteristicWrite 호출을 사용하여 다음 데이터 청크를 작성하는 것이 안전하다는 것을 읽었습니다. 그들이 틀렸거나 뭔가 복잡한 일이있었습니다. 어느 쪽이든, 나는 그 함수 호출 반환 값을 확인하는 것이 좋습니다.

+0

실제로 writeCharacteristic을 호출하는 코드를 표시 할 수 있습니까? – Emil

+0

예. 지금 추가 중입니다. – Seth

+0

음, 이상하게 보입니다. https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#WRITE_TYPE_NO_RESPONSE를 사용하고 있습니까? 또한 블루투스 hci snoop 로그를 활성화하고 나중에 Wireshark에서 로그를 검사하여 무선으로 전송 된 것을 확인할 수 있습니다. – Emil

답변

1

이제 알았습니다. onWriteCharacteristic 콜백 전에 알림이 도착하는 경우가 있습니다. 통지 콜백에서 다음 쓰기를 발행하기 때문에, 이전 쓰기는 여전히 보류 중입니다. 다음 쓰기를 실행하기 전에 onWriteCharacteristic이 호출되었는지 확인해야합니다.

+0

정말요? 예를 들어 datapoint 7을 원한다면 그 요청을 작성한 다음 onCharacteristicWrite가 성공적으로 쓰기가 진행될 때 호출 될 것이고 응답을 받으면 onCharacterisicChanged가 호출되어 데이터 포인트 8을 요청할 것입니다. onCharacteristicWrite는 응답을 받기 전에 호출되지 않습니다. – Seth

+0

예, 주변기기가 GATT 쓰기 응답을 되돌려 보내면 onCharacteristicWrite가 호출됩니다. 동시에 알림을 보내므로 처음에는 응용 프로그램에 전달되는 정의되지 않은 것 같습니다. logcat 로그에서 이전 쓰기 패킷과 비교하여 통지 이후 마지막 쓰기 응답이 검색됩니다. characteristic.getValue()에는 마지막으로 쓰거나 알린 값이 포함되어 있으므로 보내지 않은 쓰기에 대한 응답이라고 생각하는 이유입니다 (특성 값을 직접 설정했는지 기억하십시오). 어쨌든, snooplog에서 어떤 순서로 공중을 보냈는지보십시오. – Emil

+0

예, 정말 흥미 롭습니다. 그래도 말이 되네. 이 문제를 해결해 주셔서 감사합니다. +1 – Seth

관련 문제