前提・実現したいこと
タブレット(セントラル)・ウォッチ(ペリフェラル)間でBLE通信を行うプログラムを作成しています。
MTUサイズを拡張せず、50バイト前後のデータを20バイトずつ分割送信を行います。
(本当は1000バイト前後のデータを送信したい)
①分割送信開始
→BluetoothGatt.beginReliableWrite()
②分割データを各送信
→BluetoothGatt.writeCharacteristic(blechar)
③分割送信終了
→BluetoothGatt.executeReliableWrite()
上記①~③を行います。
発生している問題・エラーメッセージ
セントラル・ペリフェラルのBLE通信確立後、
1回目の分割データ送信は成功します。
(50バイト前後でも、1000バイト前後でも1回目は成功します)
しかし、2回目以降から下記のようにデータ送信に失敗します。
①分割送信開始 → 成功
②分割データを各送信 → 失敗(分割データ1回目から)
そして必ず1回目の分割データ送信後、数十秒後にBLE通信が切断されます。
(そのとき、セントラル・ペリフェラルとも切断時のコールバックが呼ばれます)
分割送信しないで、BluetoothGatt.writeCharacteristic(blechar)だけでデータ送信を行うのであれば、
何回でもデータ送信できることは確認済みです。
なにがどうなっているのか分かりません。
どうアプローチしていけばよいでしょうか。
セントラル側のプログラム
java
1 private boolean isSending = false; 2 private byte[] tmp = null; 3 private int cnt = 0; 4 private boolean isOnce = false; 5 /** 送信データ制限値 */ 6 private int LIMIT = 20; 7 8 /** 9 * 書き込み(分割) 10 */ 11 private void writeStart() { 12 13 Log.d(LOG_TAG_DATA, "-----------------分割送信開始"); 14 cnt = 0; 15 String data = ""; 16 17 try { 18 data = "abcdefghi0abcdefghi1abcdefghi2abcdefghi3abcdefghi4abcdefghi5"; 19 tmp = data.getBytes(); 20 Log.d(LOG_TAG_DATA, "ウォッチレイアウトデータ:" + data); 21 Log.d(LOG_TAG_DATA, "ウォッチレイアウトデータ:" + data.length()); 22 Log.d(LOG_TAG_DATA, "ウォッチレイアウトデータ.getByte:" + tmp.length); 23 24 /** 一回の送信でOK */ 25 if (data.length() - LIMIT <= 0) { 26 isOnce = true; 27 28 /** 分割送信 */ 29 } else { 30 boolean startFlg = mBleGatt.beginReliableWrite(); 31 Log.d(LOG_TAG_DATA, "mBleGatt.beginReliableWrite():" + startFlg); 32 doWrite(); 33 } 34 isSending = true; 35 doWrite(); 36 } catch (Exception e) { 37 e.printStackTrace(); 38 } 39 } 40 41 /** 42 * 書き込み(分割)実処理 43 */ 44 private void doWrite() { 45 46 Log.d(LOG_TAG_DATA, "-----------------分割送信開始:" + cnt); 47 String data = ""; 48 int from = 0; 49 int to = 0; 50 51 try { 52 /** カウントアップ */ 53 cnt++; 54 55 BluetoothGattCharacteristic blechar = mBleGatt.getService(UUID.fromString(CUSTOM_SURVICE_UUID)).getCharacteristic(UUID.fromString(CUSTOM_CHARACTERSTIC_UUID)); 56 57 if (isSending == true) { 58 59 /** 分割 */ 60 if (LIMIT*cnt <= tmp.length) { 61 from = LIMIT*(cnt-1); 62 to = LIMIT*cnt; 63 if (LIMIT*(cnt+1) > tmp.length) { 64 to = tmp.length; 65 isSending = false; 66 } 67 /** 一回 */ 68 } else { 69 from = LIMIT*(cnt-1); 70 to = tmp.length; 71 isSending = false; 72 } 73 74 blechar.setValue(Arrays.copyOfRange(tmp, from, to)); 75 boolean result = mBleGatt.writeCharacteristic(blechar); 76 Log.d(LOG_TAG_DATA, "writeCharacteristic():" + result); 77 78 } else { 79 80 if (isOnce == true) { 81 isOnce = false; 82 return; 83 } 84 85 boolean finishFlg = mBleGatt.executeReliableWrite(); 86 Log.d(LOG_TAG_DATA, "mBleGatt.executeReliableWrite():" + finishFlg); 87 cnt = 0; 88 } 89 90 } catch (Exception e) { 91 e.printStackTrace(); 92 } 93 } 94
ペリフェラル側のプログラム
java
1 2 /** コールバック作成 */ 3 private BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() { 4 5 @Override 6 public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { 7 if(newState == BluetoothProfile.STATE_CONNECTED){ 8 mDevice = device; 9 Log.d(LOG_TAG_DATA, "-----------------------接続完了"); 10 } else { 11 Log.d(LOG_TAG_DATA, "-----------------------接続解除"); 12 mDevice = null; 13 } 14 } 15 16 @Override 17 public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { 18 super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value); 19 20 Log.d(LOG_TAG_DATA, "----------------------------onCharacteristicWriteRequest"); 21 22 if (value != null) { 23 byte[] c = null; 24 int length = 0; 25 26 if (recvByte == null) { 27 c = new byte[value.length]; 28 } else { 29 c = new byte[recvByte.length + value.length]; 30 /** recvByte→cにコピー 31 * (コピー元配列、コピー元配列の開始位置、コピー先配列、コピー先配列開始位置、コピーする要素数) */ 32 System.arraycopy(recvByte, 0, c, 0, recvByte.length); 33 length = recvByte.length; 34 } 35 /** value→cにコピー */ 36 System.arraycopy(value, 0, c, length, value.length); 37 recvByte = c; 38 39 Log.d(LOG_TAG_DATA, "recvByte.length!!!!:" + recvByte.length); 40 Log.d(LOG_TAG_DATA, "recvByte.value:" + new String(recvByte)); 41 } 42 43 mBtGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, "wearWrite".getBytes()); 44 } 45 46 /** 分割送信後に呼ばれる */ 47 @Override 48 public void onExecuteWrite (BluetoothDevice device, int requestId, boolean execute) { 49 Log.d(LOG_TAG_DATA, "--------------------分割完了/onReliableWriteCompleted:recvByte: " + new String(recvByte)); 50 Log.d(LOG_TAG_DATA, "--------------------分割完了/onReliableWriteCompleted:recvByte.length: " + new String(recvByte).length()); 51 /** 初期化 */ 52 recvByte = null; 53 } 54 };
補足情報(FW/ツールのバージョンなど)
セントラル:AndroidOS 7
ペリフェラル:WearOS 2