質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Bluetooth

Bluetoothとは短距離の間でデータを交換するための無線通信規格である。固定・モバイル両方のデバイスから、短波の電波送信を行うことで、高いセキュリティをもつパーソナルエリアネットワーク(PAN)を構築する。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Wear

Android Wearとは、Googleが発表した腕時計型ウェアラブルデバイス(スマートウォッチ)向けのプラットフォームです。GoogleのAndroid OSをベースにしており、情報の入手・管理などを行うことができます。

Q&A

1回答

5739閲覧

AndroidのBLE通信で分割送信を行うと、1回目は成功するのに、2回目以降から失敗する

pakumo

総合スコア12

Bluetooth

Bluetoothとは短距離の間でデータを交換するための無線通信規格である。固定・モバイル両方のデバイスから、短波の電波送信を行うことで、高いセキュリティをもつパーソナルエリアネットワーク(PAN)を構築する。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Wear

Android Wearとは、Googleが発表した腕時計型ウェアラブルデバイス(スマートウォッチ)向けのプラットフォームです。GoogleのAndroid OSをベースにしており、情報の入手・管理などを行うことができます。

0グッド

0クリップ

投稿2019/07/02 14:48

編集2019/07/02 14:55

前提・実現したいこと

タブレット(セントラル)・ウォッチ(ペリフェラル)間で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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2019/07/02 16:24

これだけログが入っているのですから, 成功から失敗, 切断までのログも追記されては如何でしょう. > ②分割データを各送信 → 失敗(分割データ1回目から) 失敗とはどういう状況でしょう. 例外が発生するのでしょうか. 50バイトを20バイトずつ送信するのでしたらループがあると思うのですが, 見当たりません... どのようなクラス内にあるのか分かりませんが, 読み難いコードになっていると思います. 流れをご確認されて, 出来れば作りを見直されては如何でしょうか.
guest

回答1

0

セントラル側を無理に2つのメソッドにせず, 「実現したいこと」に書かれた通りに書けば, 次のようになるでしょうか.

※切り貼り修正しただけで, コンパイル等していません.

java

1/** 送信データ制限値 */ 2static private final int LIMIT = 20; 3/** 4 * 書き込み(分割) 5 */ 6public void writeStart() throws Exception { 7 Log.d(LOG_TAG_DATA, "-----------------分割送信開始"); 8 9 String data = "abcdefghi0abcdefghi1abcdefghi2abcdefghi3abcdefghi4abcdefghi5"; 10 byte[] tmp = data.getBytes(); 11 Log.d(LOG_TAG_DATA, "ウォッチレイアウトデータ:" + data); 12 Log.d(LOG_TAG_DATA, "ウォッチレイアウトデータ:" + data.length()); 13 Log.d(LOG_TAG_DATA, "ウォッチレイアウトデータ.getByte:" + tmp.length); 14 15 BluetoothGattCharacteristic blechar = mBleGatt.getService(UUID.fromString(CUSTOM_SURVICE_UUID)).getCharacteristic(UUID.fromString(CUSTOM_CHARACTERSTIC_UUID)); 16 17 if (tmp.length() <= LIMIT) { 18 /** 一回の送信でOK */ 19 blechar.setValue(tmp); 20 boolean result = mBleGatt.writeCharacteristic(blechar); 21 Log.d(LOG_TAG_DATA, "writeCharacteristic():" + result); 22 23 } else { 24 /** 分割送信 */ 25 boolean startFlg = mBleGatt.beginReliableWrite(); 26 Log.d(LOG_TAG_DATA, "mBleGatt.beginReliableWrite():" + startFlg); 27 28 for(int from=0; from<tmp.length; from+=LIMIT) { 29 int to = Math.min(from+LIMIT, tmp.length); 30 blechar.setValue(Arrays.copyOfRange(tmp, from, to)); 31 boolean result = mBleGatt.writeCharacteristic(blechar); 32 Log.d(LOG_TAG_DATA, "writeCharacteristic():" + result); 33 } 34 35 boolean finishFlg = mBleGatt.executeReliableWrite(); 36 Log.d(LOG_TAG_DATA, "mBleGatt.executeReliableWrite():" + finishFlg); 37 } 38}

投稿2019/07/02 17:03

編集2019/07/02 17:09
jimbe

総合スコア13168

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問