BluetoothGattServer всегда отключается через 30 секунд

Я пытался выяснить, как заставить эти телефоны общаться друг с другом через 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 секунд каждый раз.

1 ответ

Согласно спецификации ядра, для ATT

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

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

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

Другие вопросы по тегам