BluetoothGattServer всегда отключается через 30 секунд - PullRequest
0 голосов
/ 27 февраля 2019

Я пытался выяснить, как заставить эти телефоны общаться друг с другом через Bluetooth.У меня телефон Android настроен как периферийное устройство, и на моем iPhone запущено приложение nrf connect .Я могу рекламировать и подключаться к телефону Android с iPhone, и я могу подписаться на уведомления и видеть обновленную характеристику.Проблема в том, что если я не отправляю характерное уведомление, примерно через 7-10 секунд соединение теряется.Я получаю обратный вызов обработчика обратного вызова connectionStateChanged, и я не могу понять, что является причиной этого.Я не думаю, что это приложение NRF, потому что я связан с другими вещами, и он просто остается на связи всегда.Я что-то упускаю?

Вот код:

private BluetoothManager bluetoothManager;
private BluetoothGattServer gattServer;
private BluetoothGattCharacteristic test_characteristic;
private BluetoothDevice connected_device;


private BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() {
    @Override
    public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
        super.onConnectionStateChange(device, status, newState);
        if (newState == 2){ //CONNECTED
            connected_device = device;
        }
        Log.i("chase", "Connection state changed: "+newState);
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    BluetoothRegulator.sharedInstance().appContext = getApplicationContext();
    bluetoothManager = (android.bluetooth.BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
    BluetoothRegulator.sharedInstance().initialize(bluetoothManager);

    if( ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
    }


    gattServer = bluetoothManager.openGattServer(this, gattServerCallback);
    String uuid_string = "92D9D153-9BE6-43FF-9672-3E2904628B9D";
    BluetoothGattService service = new BluetoothGattService(UUID.fromString(uuid_string), BluetoothGattService.SERVICE_TYPE_PRIMARY);

    uuid_string = "43FF0001-9BE6-43FF-9672-3E2904628B9D";
    test_characteristic = new BluetoothGattCharacteristic(
            UUID.fromString(uuid_string),
            BluetoothGattCharacteristic.PROPERTY_BROADCAST | BluetoothGattCharacteristic.PROPERTY_NOTIFY | BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE,
            BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
    test_characteristic.setValue( ""+System.currentTimeMillis() );
    service.addCharacteristic(test_characteristic);
    gattServer.addService(service);

    findViewById(R.id.send_data_btn).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            shot_detected_characteristic.setValue( ""+System.currentTimeMillis() );
            gattServer.notifyCharacteristicChanged(connected_device, shot_detected_characteristic, false);
        }
    });

    findViewById(R.id.advertise).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            advertise();
        }
    });

}
private void advertise() {
    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    BluetoothLeAdvertiser advertiser = adapter.getBluetoothLeAdvertiser();
    AdvertiseSettings settings = new AdvertiseSettings.Builder()
            .setAdvertiseMode( AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY )
            .setTxPowerLevel( AdvertiseSettings.ADVERTISE_TX_POWER_HIGH )
            .setConnectable( true )
            .build();
    String uuid_string = "92C9D164-9BE6-43FF-9672-3E2804618B9C";
    ParcelUuid pUuid = new ParcelUuid( UUID.fromString( uuid_string ) );

    AdvertiseData data = new AdvertiseData.Builder()
            .setIncludeDeviceName( true )
            .addServiceData( pUuid, "TEST".getBytes( Charset.forName( "UTF-8" ) ) )
            .build();

    AdvertiseCallback advertisingCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            Log.e( "BLE", "Advertising Started");
            super.onStartSuccess(settingsInEffect);
        }

        @Override
        public void onStartFailure(int errorCode) {
            Log.e( "BLE", "Advertising onStartFailure: " + errorCode );
            super.onStartFailure(errorCode);
        }
    };
    advertiser.startAdvertising( settings, data, advertisingCallback );
}

Редактировать : На самом деле, я замечаю, что это не имеет никакого отношения к бездействию,Фактически каждый раз он отключается на 30-секундной отметке.

EDIT : Поэтому я добавил onCharacteristicRead & onCharacteristicWrite обратные вызовы.Но это, кажется, ничего не меняет, и это имеет смысл для меня, потому что я ничего не делаю в них, кроме как вызвать super.onCharacteristicRead() в любом случае.Кроме того, они не будут вызваны, если я не делаю чтения и записи.И кажется, что Bluetooth должен оставаться подключенным более 30 секунд, даже если нет запроса на чтение или запись.

private BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() {
    @Override
    public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
        super.onConnectionStateChange(device, status, newState);
        if (newState == 2){
            connected_device = device;
            advertiser.stopAdvertising(new AdvertiseCallback() {});
        }
    }

    @Override
    public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
    }

    @Override
    public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
        super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
    }

};

РЕШЕНИЕ

Таким образом, проблема заключается в обратном вызове onCharacteristicReadRequest, Согласно документам :

Приложение должно вызвать BluetoothGattServer # sendResponse для завершения запроса.

Так что, как только я обновил свой обратный вызов, чтобы он выглядел какэто:

@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
    super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
    gattServer.sendResponse(device, requestId, 1, offset, characteristic.getValue());
}

, а затем каждые несколько секунд считывает данные, после чего время ожидания не отключается.

1 Ответ

0 голосов
/ 28 февраля 2019

В соответствии с спецификацией основного ядра , для ATT

Срок действия транзакции, не завершенной в течение 30 секунд, истекает.

На практике этообычно проявляется как разъединение на одной стороне соединения.

Для некоторых типов запросов GATT требуются ответы (например, индикация, запросы на чтение, запросы на запись).Не похоже, что вы реализуете обратные вызовы, такие как onCharacteristicReadRequest & onCharacteristicWriteRequest, в вашей реализации сервера Gatt, которые могут привести к этой проблеме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...