Bluetooth Low Energyを用いてプログラムを開発しています。
送信側にて64msec周期でキャラクタリスティックを更新し、更新通知が受信側に届いていることをパケットキャプチャ(nRF51 dongle + Wireshark)で確認しました。
※受信間隔にバラツキはありますが、概ね64msec周期で受信できています。
2501 112.789743 Slave_0x283eb820 Master_0x283eb820 ATT 53 Rcvd Handle Value Notification, Handle: 0x0019 (Unknown) 2503 112.898854 Slave_0x283eb820 Master_0x283eb820 ATT 53 Rcvd Handle Value Notification, Handle: 0x0019 (Unknown) 2505 112.907883 Slave_0x283eb820 Master_0x283eb820 ATT 53 Rcvd Handle Value Notification, Handle: 0x0019 (Unknown) 2507 113.017212 Slave_0x283eb820 Master_0x283eb820 ATT 53 Rcvd Handle Value Notification, Handle: 0x0019 (Unknown) 2511 113.030233 Slave_0x283eb820 Master_0x283eb820 ATT 53 Rcvd Handle Value Notification, Handle: 0x0019 (Unknown) 2513 113.139254 Slave_0x283eb820 Master_0x283eb820 ATT 53 Rcvd Handle Value Notification, Handle: 0x0019 (Unknown) 2515 113.147382 Slave_0x283eb820 Master_0x283eb820 ATT 53 Rcvd Handle Value Notification, Handle: 0x0019 (Unknown) 2519 113.266009 Slave_0x283eb820 Master_0x283eb820 ATT 53 Rcvd Handle Value Notification, Handle: 0x0019 (Unknown) 2521 113.273321 Slave_0x283eb820 Master_0x283eb820 ATT 53 Rcvd Handle Value Notification, Handle: 0x0019 (Unknown) 2523 113.382328 Slave_0x283eb820 Master_0x283eb820 ATT 53 Rcvd Handle Value Notification, Handle: 0x0019 (Unknown)
気がかりな点として、1回の更新通知でonCharacteristicChanged()が複数回呼び出されています。
これは正常な動作(仕様)なのでしょうか?
もしくは、このような事象が発生したという方はいらっしゃいますでしょうか?
事象が発生した際のソースコードは以下の通りです。
※SERVICE_UUID、CHARACTERISTIC_UUIDは伏せ字にしてあります。
Java
1// import 2import android.bluetooth.BluetoothAdapter; 3import android.bluetooth.BluetoothDevice; 4import android.bluetooth.BluetoothGatt; 5import android.bluetooth.BluetoothGattCallback; 6import android.bluetooth.BluetoothGattCharacteristic; 7import android.bluetooth.BluetoothGattDescriptor; 8import android.bluetooth.BluetoothGattService; 9import android.bluetooth.BluetoothManager; 10import android.bluetooth.BluetoothProfile; 11import android.bluetooth.le.BluetoothLeScanner; 12import android.bluetooth.le.ScanCallback; 13import android.bluetooth.le.ScanResult; 14import android.bluetooth.le.ScanFilter; 15import android.bluetooth.le.ScanSettings; 16 17import android.content.Context; 18import android.os.ParcelUuid; 19import android.support.v7.app.AppCompatActivity; 20import android.os.Bundle; 21import android.util.Log; 22 23import java.util.ArrayList; 24import java.util.Arrays; 25import java.util.Locale; 26import java.util.UUID; 27 28import static android.bluetooth.BluetoothGatt.CONNECTION_PRIORITY_HIGH; 29 30 31public class MainActivity extends AppCompatActivity { 32 // グローバル変数定義 33 private ArrayList mScanFilterList; 34 private ScanSettings mScanSettings; 35 private BluetoothLeScanner mBtLeScanner; 36 private BluetoothDevice mBtDevice; 37 private BluetoothGatt mBtGatt; 38 private BluetoothGattCharacteristic mBtGattCharacteristic; 39 private byte[] m_byReceiveData = new byte[20]; 40String strMsg; 41long m_CntNG = 0; 42long m_CntOK = 0; 43 44 // UUID定義 45 // 対象のサービスUUID. 46 private static final String SERVICE_UUID = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX1"; 47 // キャラクタリスティックUUID. 48 private static final String CHARACTERISTIC_UUID = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX2"; 49 // キャラクタリスティック設定UUID(固定値). 50 private static final String CHARACTERISTIC_UUID_CONFIG = "00002902-0000-1000-8000-00805f9b34fb"; 51 52 // 初期処理 53 @Override 54 protected void onCreate(Bundle savedInstanceState) { 55 super.onCreate(savedInstanceState); 56 57 BluetoothManager btManager; 58 BluetoothAdapter btAdapter; 59 60 setContentView(R.layout.activity_main); 61 62 // 前回受信データの初期化 63 for(int i=0; i<m_byReceiveData.length; i++) { 64 m_byReceiveData[i] = 0x00; 65 } 66 67 btManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE); 68 btAdapter = btManager.getAdapter(); 69 70 // フィルタを設定する。 71 ScanFilter scanFilter = new ScanFilter.Builder() 72 .setServiceUuid(ParcelUuid.fromString(SERVICE_UUID)).build(); 73 mScanFilterList = new ArrayList(); 74 mScanFilterList.add(scanFilter); 75 76 mScanSettings = new ScanSettings.Builder() 77 .setScanMode(ScanSettings.SCAN_MODE_BALANCED).build(); 78 79 // スキャンを開始する。 80 mBtLeScanner = btAdapter.getBluetoothLeScanner(); 81 mBtLeScanner.startScan(mScanFilterList, mScanSettings, mScanCallback); 82 } 83 84 // スキャン結果コールバック関数 85 private final ScanCallback mScanCallback = new ScanCallback() { 86 // スキャン結果通知処理 87 @Override 88 public void onScanResult(int callbackType, ScanResult result) { 89 super.onScanResult(callbackType, result); 90 91 // デバイスを発見した 92 if((null != result) && (null != result.getDevice())) { 93 mBtDevice = result.getDevice(); 94 95 // デバイスに接続する。 96 mBtGatt = mBtDevice.connectGatt(getApplicationContext(), false, mGattCallback); 97 } 98 } 99 }; 100 101 // GATTコールバック関数 102 private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback(){ 103 // 接続状態変化検出処理 104 @Override 105 public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState){ 106 // 接続状況が変化したら実行. 107 if(newState == BluetoothProfile.STATE_CONNECTED) { 108 // 接続に成功したらサービスを検索する. 109 gatt.discoverServices(); 110 } else if(newState == BluetoothProfile.STATE_DISCONNECTED) { 111 // 接続が切れたらGATTを空にする. 112 if(mBtGatt != null){ 113 mBtGatt.close(); 114 mBtGatt = null; 115 } 116 117 // スキャンを再開する。 118 mBtLeScanner.startScan(mScanFilterList, mScanSettings, mScanCallback); 119 } 120 } 121 122 // サービス検出処理 123 @Override 124 public void onServicesDiscovered(BluetoothGatt gatt, int status){ 125 BluetoothGattService bleService; 126 boolean bRet; 127 BluetoothGattDescriptor bleDescriptor; 128 129 // Serviceが見つかったら実行. 130 if(status == BluetoothGatt.GATT_SUCCESS) { 131 // UUIDが同じかどうかを確認する. 132 bleService = gatt.getService(UUID.fromString(SERVICE_UUID)); 133 if(bleService != null){ 134 // 指定したUUIDを持つCharacteristicを確認する. 135 mBtGattCharacteristic = bleService.getCharacteristic(UUID.fromString(CHARACTERISTIC_UUID)); 136 if(mBtGattCharacteristic != null) { 137 // Service, CharacteristicのUUIDが同じならBluetoothGattを更新する. 138 mBtGatt = gatt; 139 140 // Notifyを高速で受け取るための要求 141 mBtGatt.requestConnectionPriority(CONNECTION_PRIORITY_HIGH); 142 143 // キャラクタリスティックが見つかったら、Notificationをリクエスト. 144 bRet = mBtGatt.setCharacteristicNotification(mBtGattCharacteristic, true); 145 146 if(true == bRet) { 147 // Characteristic の Notificationを有効化する. 148 bleDescriptor = mBtGattCharacteristic.getDescriptor(UUID.fromString(CHARACTERISTIC_UUID_CONFIG)); 149 if(null != bleDescriptor) { 150 bleDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); 151 mBtGatt.writeDescriptor(bleDescriptor); 152 } 153 154 // scan 終了 155 mBtLeScanner.stopScan(mScanCallback); 156 } 157 } 158 } 159 } 160 } 161 162 // 更新通知受信処理 163 @Override 164 public synchronized void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic){ 165 super.onCharacteristicChanged(gatt, characteristic); 166 167 byte byReceiveData[]; 168 169 // キャラクタリスティックのUUIDをチェック(getUuidの結果が全て小文字で帰ってくるのでUpperCaseに変換) 170 if(CHARACTERISTIC_UUID.equals(characteristic.getUuid().toString().toUpperCase())){ 171 // characteristicを取得する。 172 byReceiveData = characteristic.getValue(); 173 174 // データ長が異なる場合は処理をスキップする。 175 if(byReceiveData.length != m_byReceiveData.length) { 176strMsg = String.format(Locale.US, "***** Length (%d:%d) *****", byReceiveData.length, m_byReceiveData.length); 177Log.e("TAG", strMsg); 178 return; 179 } 180 181 // 前回と同一データの場合は処理スキップする。 182 if(Arrays.equals(byReceiveData, m_byReceiveData)) { 183m_CntNG++; 184strMsg = String.format("xxx Receive NG(%d)", m_CntNG); 185Log.e("TAG", strMsg); 186 return; 187 } 188 else { 189m_CntOK++; 190strMsg = String.format("ooo Receive OK(%d)", m_CntOK); 191Log.e("TAG", strMsg); 192 System.arraycopy(byReceiveData, 0, m_byReceiveData, 0, m_byReceiveData.length); 193 } 194 } 195 } 196 }; 197}
実行結果は以下のように出力されています。
08-10 14:34:38.108 E: ooo Receive OK(1)
08-10 14:34:38.108 E: xxx Receive NG(1)
08-10 14:34:38.109 E: ooo Receive OK(2)
08-10 14:34:38.110 E: xxx Receive NG(2)
08-10 14:34:38.156 E: ooo Receive OK(3)
08-10 14:34:38.157 E: xxx Receive NG(3)
08-10 14:34:38.258 E: ooo Receive OK(4)
08-10 14:34:38.259 E: xxx Receive NG(4)
08-10 14:34:38.316 E: ooo Receive OK(5)
08-10 14:34:38.317 E: xxx Receive NG(5)
送信する更新通知は20byteです。
送信側、受信側共にAndroid(7.0)、Bluetooth V4.2です。
開発環境はAndroidStudio(3.0.1)です。
アドバイス、宜しく御願い致します。

回答3件
あなたの回答
tips
プレビュー