2017-02-07 25 views
1

Проблемымаяков + Bluetooth связи (профиль ГАТТ) не работает нормально [BLE]

Я периферийное устройство, которое излучает маяки с определенным идентификатором. С моим смартфоном (который играет центральную роль) выполняется поиск маяка периферийного устройства. Когда он находит правильный маяк, он начинает связь Bluetooth через профиль GATT. В первый раз, когда устройства подключены, данные отправляются от одного к другому правильно, но во второй раз (у меня есть таймер, чтобы попытаться подключить оба устройства каждые 20 секунд), соединение не работает, я не знаю почему ... Я должен убить процесс приложения и снова открыть его, чтобы он снова работал.

Что я сделал

Для маяков, я использую altbeacon, поэтому код для обнаружения маяков в центральном аппарате заключается в следующем:

@Override 
public void onBeaconServiceConnect() { 
    beaconManager.setRangeNotifier(new RangeNotifier() { 
     @Override 
     public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) { 
      Log.i(TAG, "Beacon detected!"); 
      if (beacons.size() > 0 && Utils.getUserData(getApplicationContext(), "id").compareTo("-1") != 0) { 
       if(region.getId1().compareTo(Identifier.parse(identifier))==0) { 
        Beacon beacon = beacons.iterator().next(); 
        Log.i(TAG, "The first beacon I see is about " + beacon.getDistance() + " meters away. " 
          + region.getId1()); 
        String mac = beacon.getBluetoothAddress(); 
        Log.i("MAC", "MAC: "+mac); 
        CustomBluetoothManager customBluetoothManager = CustomBluetoothManager.getInstance(getApplicationContext()); 
        if(!customBluetoothManager.isScanning()) { 
         customBluetoothManager.scanLeDevice(true, mac); 
        } 
       } 
      } 
     } 
    }); 

    try { 
     beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", Identifier.parse(identifier), 
       null, null)); 
    } catch (RemoteException e) { } 
} 

Когда маяк обнаружен, то scanLeDevice называется:

public void scanLeDevice(final boolean enable, String mac) { 
    target_mac = mac; 
    mHandler = new Handler(); 

    if (enable) { 
     // Stops scanning after a pre-defined scan period. 
     mHandler.postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       mScanning = false; 
       mBluetoothAdapter.stopLeScan(mLeScanCallback); 
      } 
     }, SCAN_PERIOD); 

     mScanning = true; 
     mBluetoothAdapter.startLeScan(mLeScanCallback); 
    } else { 
     mScanning = false; 
     mBluetoothAdapter.stopLeScan(mLeScanCallback); 
    } 
} 

и вот код mLeScanCallback:

private BluetoothAdapter.LeScanCallback mLeScanCallback = 
     new BluetoothAdapter.LeScanCallback() { 
      @Override 
      public void onLeScan(final BluetoothDevice device, int rssi, 
           byte[] scanRecord) { 
       long epoch = System.currentTimeMillis()/1000; 
       SharedPreferences prefs = context.getSharedPreferences(
         "epoch", Context.MODE_PRIVATE); 
       long epochStored = prefs.getLong("epoch", 0); 

       if (device.getAddress().compareTo(MAC) == 0 && after20Seconds) { 
        prefs.edit().putLong("epoch", epoch).apply(); 
        Log.d("epoch", Long.toString(epoch)); 
        mDeviceAddress = device.getAddress(); 
        final Intent gattServiceIntent = new Intent(context, BluetoothLeService.class); 
        context.bindService(gattServiceIntent, mServiceConnection, context.BIND_AUTO_CREATE); 
       } 
      } 
     }; 

Мне пришлось жестко указывать MAC-адрес, поскольку MAC-адрес, который содержит маяки в пакетах, не совпадает с реальным MAC-адресом устройства (это определение BLE, но я точно не знаю, как оно работает).

Наконец, когда данные посылаются, я закрываю и отключить канал Bluetooth® и я пытался отвязать обслуживание тоже, но ничего не работает:

@Override 
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 
     super.onCharacteristicWrite(gatt, characteristic, status); 
     disconnect(); 
     close(); 
     unbindService(mServiceConnection); 
    } 

Таким образом, с помощью этого кода, в первый раз что устройства подключены, данные отправляются правильно, но через 20 секунд во второй попытке никогда не будет установлено сообщение.

Вопросы

  1. Любая идея, что может быть проблема?
  2. Как работает BLE? В сигнальных пакетах MAC является поддельным по соображениям безопасности. Однако, если я получаю это от маяков сканирования приложений, и я жестко вписываю его в приложение, работа работает ... Я думаю, что это не должно работать.
  3. Как я могу получить MAC-адрес устройства из пакета маяков?
  4. Знаете ли вы какой-либо образец, чтобы использовать маяки с Bluetooth-связью?
  5. Если я остановлю сканирование с помощью метода «mBluetoothAdapter.stopLeScan (mLeScanCallback)», кажется, что сканирование действительно не останавливается ... Это нормально? Журнал непрерывно показывает "BluetoothLeScanner: startRegisteration: mLeScanClients = {org.altbeacon.beacon.service.scanner.CycledLeScannerForLollipop $ 4 @ 5445b45 = android.bluetooth.le.BluetoothLeScanner ......"
+0

Зачем вам нужен альтбекон? от того, что я понимаю. Ваше требование основано на центральных и периферийных ролях gatt, оно вращается вокруг MAC-адресов (ов) устройств. (между тем я также думаю о том, почему его проблема во второй раз, помните, что сталкиваемся с чем-то похожим) – user2450263

+0

Спасибо за ваш ответ! Мне нужны маяки, чтобы знать, когда пользователь находится рядом с периферийным устройством ... Таким образом, мы можем избежать того, что приложение постоянно сканирует устройства Bluetooth, которые находятся вокруг пользователя. – adri1992

+0

'scanLeDevice' и его обратный вызов это так или иначе, вам просто нужно вычислить значение rssi для близости - для вычисления того, находится ли пользователь рядом с устройством. – user2450263

ответ

1

You не может читать MAC-адрес с помощью API Android BLE. Как вы знаете, он подделывается поддельным MAC, который сопоставляется с реальным ОС.Так эта линия не будет надежно:

device.getAddress().compareTo(MAC) == 0

Это может быть то, что вызывает подключение к сбою второго зубца. Тот факт, что он работает при первом запуске, является неожиданным и, вероятно, только благодаря детерминированной реализации алгоритма вращения спуфинга MAC для Android. Тот факт, что он не работает со вторым подключением

Вам нужно будет найти другой способ найти подходящее устройство для подключения, возможно, с помощью маякового идентификатора.

Трудно найти хороший пример кода для подключения к маякам, поскольку это не типичный вариант использования. Как правило, они рассматриваются как устройства передачи только по мере их разработки. Именно поэтому Android Beacon Library не предоставляет инструменты для подключения к службам BLE - стандартная реализация для всех производителей маяковых радиосигналов отсутствует. Тем не менее, ваш таможенный подход является разумным.

Поймите, что Android Beacon Library выполняет собственное сканирование Bluetooth для обнаружения маяков. Вот почему, несмотря на то, что вы остановили свое сканирование, вы все равно видите результаты сканирования в журнале. Это происходит из библиотеки.

Полное раскрытие информации: Я являюсь ведущим разработчиком проекта Android Beacon Library с открытым исходным кодом.

+0

. Я хотел бы поблагодарить вас за этот ответ и вашу помощь, которую я получил ранее. Я использовал библиотеку RadiusNetworks android ibeacon до того, как раздались авторские права/товарные знаки Apple :). С тех пор реализация Altbeacon и eddystone прошла долгий путь. Я бы сказал, что реализация в этом конкретном вопросе будет связана с [BluetoothGatt] (https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html) и связанными с ним классами. – user2450263

 Смежные вопросы

  • Нет связанных вопросов^_^