Почему обновление статуса `ACTION_GATT_DISCONNECTED` занимает так много времени?

#android #bluetooth-lowenergy

#Android #bluetooth-низкое энергопотребление

Вопрос:

Я использую Bluetooth Low Energy для подключения к моему Galaxy S4. После подключения статус подключения будет обновлен в функции

 private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        String intentAction;
        if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
            Log.d(TAG,"Connected");                

        } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
            Log.d(TAG,"Disconnected");                
        }
    }
}
  

В котором статус, полученный из

 // Implements callback methods for GATT events that the app cares about.  For example,
    // connection change and services discovered.
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction);
                Log.i(TAG, "Connected to GATT server.");
                // Attempts to discover services after successful connection.
                Log.i(TAG, "Attempting to start service discovery:"  
                        mBluetoothGatt.discoverServices());

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG, "Disconnected from GATT server.");
                broadcastUpdate(intentAction);
            }
        }
  

Однако ACTION_GATT_DISCONNECTED обновление занимает 10 секунд, когда соединение между устройством BLE и телефоном потеряно. В случае ACTION_GATT_CONNECTED он обновляется так быстро, примерно за 1 секунду. Возможно ли уменьшить статус отключения в BLE? Спасибо всем

Комментарии:

1. Что вы имеете в виду, говоря «уменьшить статус отключения»? Что занимает 10 секунд для обновления? Что именно делает broadcastUpdate?

2. Спасибо Nebr за рассмотрение моего вопроса. Я приведу вам пример того, что я сделал. В моем BLE есть две кнопки: включить и выключить. Когда он включится, BLE соединится с моим телефоном. Для отображения журнала требуется около 1 секунды Connected . Когда эти устройства подключены, я выключаю свое устройство BLE, но для отображения требуется около 10 секунд Disconnected . Я хочу сократить это время.

3. На самом деле это странно. Отключение — это просто запрос на завершение на канальном уровне, на который даже не нужно отвечать — одна сторона может отключиться без согласия другой. Можете ли вы изолировать проблемную область? Каково условие для отображения «Отключено»? Вы ждете события подтверждения завершения с более низкого уровня? Можете ли вы проверить, что делает уровень связи, когда вы отключаете устройства? Может быть, у вас где-то истекает тайм-аут в 10 секунд?

4. Вы экспериментировали с подключением BLE? Я использую пример кода BLE chat

5. Извините, у меня нет этого примера кода. И это, вероятно, не сильно поможет. Необходимо будет отладить существующую систему. Я бы поставил свои деньги на предположение, что при попытке отключения возникает тайм-аут, потому что система ожидает события, которое никогда не наступает, но без дополнительной информации (что делает broadcastUpdate, когда обновляется отображение пользовательского интерфейса и т.д.) Это будет невозможно выяснить.

Ответ №1:

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

 // Link supervision timeout is measured in N * 10ms
int timeout = 2000; // 20s
  

Соответствующий код, начинающийся со строки 1646, можно найти в com.android.bluetooth.gatt.GattService

https://android.googlesource.com/platform/packages/apps/Bluetooth/ /2b42a4906be952d3761d8b47134fba5a277a7765/src/com/android/bluetooth/gatt/GattService.java

—- Редактировать —-

Более серьезной проблемой, по-видимому, является известная ошибка с lollipop и kitcat, при которой bluedroid кэширует устройства во время обнаружения, когда это не предполагается, см. Проблема https://code.google.com/p/android/issues/detail?id=81130amp;q=BLEamp;sort=-starsamp;colspec=ID Status Priority Owner Summary Stars Reporter Opened

Изменить время ожидания невозможно, если вы не можете скомпилировать свое собственное системное пзу aosp и перепрошить его на устройство.

Существует возможный взлом для решения этой проблемы, но это не рекомендуется, потому что он обращается к скрытому внутреннему API, который может не существовать, начиная с marshmallow (поскольку bluedroid отказался от bluez).

Взлом:

После вызова disconnect и close принудительно обновите кэш обнаружения с помощью рефлекторного вызова метода refresh.

 BluetoothGatt localBluetoothGatt = gatt;
Method localMethod = localBluetoothGatt.getClass().getMethod("refresh", new Class[0]);
if (localMethod != null) {
    localMethod.invoke(localBluetoothGatt, new Object[0])).booleanValue();
}
  

Комментарии:

1. Спасибо. Можем ли мы изменить время?

2. Спасибо за ваше решение. Тем не менее, я попробовал это, но у него такая же проблема. Время повторного подключения все еще велико

3. @user8430 Может быть, попробовать другой компонент, лично мне нравится hm-10.

4. Как вы думаете, hm-10 может подключаться быстрее, чем мое устройство csr 1010? Вы использовали его раньше?

5. Я использовал его раньше и знаю, что это высококачественный чип, однако моя интеграция была в устройство Android, требующее специального последовательного драйвера, поэтому я имел полный контроль над стеком без ограничений, с которыми сталкиваетесь вы. Поэтому я не уверен, исправит ли это ситуацию для вас.

Ответ №2:

Какое устройство BLE вы используете для проверки соединения?. Возможно, что устройство действительно закрывает соединение через некоторое время. В некоторых случаях устройство BLE через некоторое время закроет соединение, потому что ему, возможно, придется записать некоторые запрошенные вами характеристики. В некоторых случаях определение момента закрытия соединения зависит от встроенного кода устройства.

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

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

Комментарии:

1. Мое устройство имеет csr 1010 следующим образом broadband.se/shop/bluetooth/bluetooth-smart/devboard /…

2. Я попытался отключиться, вызвав функцию disconnect(), она отключится напрямую. Но когда я снова подключаюсь. у него также такое же время задержки проблемы

3. ОК… Итак, устройство не отключается автоматически, и вы отключаетесь через приложение, а после отключения при повторной попытке подключения вы видите задержку. Это правильно?

4. В устройстве BLE есть переключатель для отключения при выключении питания. Однако состояние соединения по-прежнему остается подключенным, когда я выключаю питание. Через 10 секунд приложение. состояние соединения будет обновлено как отключенное. Чтобы решить эту проблему, мое устройство отправляет команду отключить его вручную. Когда я получу команду, я отключусь с помощью функции disconnect() . После этого я повторно подключаю его, вызывая функцию connect, но время все еще велико. Я думаю, что интервал времени составляет около 10 ~ 20 секунд

5. Можете ли вы попробовать вызвать gatt.close() также после disconnect()