Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Most of the time the connection does not work #445

Open
dan-developer opened this issue Dec 4, 2022 · 7 comments
Open

Most of the time the connection does not work #445

dan-developer opened this issue Dec 4, 2022 · 7 comments
Labels

Comments

@dan-developer
Copy link

I've been trying to find a solution for this error for two days now and I can't understand what happens to the connection not working. I have to try many, many times until the connection works.

Device: Samsung A13
Android version: 12

Log from logcat:

04 12:27:54.427 18420 18551 D BluetoothGatt: connect() - device: FE:EB:A9:02:1B:78, auto: false
12-04 12:27:54.427 18420 18551 I BluetoothAdapter: isSecureModeEnabled
12-04 12:27:54.428  1573  3519 D BtConfig.SecureMode: isSecureModeOn:false
12-04 12:27:54.428 18420 18551 D BluetoothGatt: registerApp()
12-04 12:27:54.429 18420 18551 D BluetoothGatt: registerApp() - UUID=31e09b9f-c264-41ea-bdd8-b17c8a835759
12-04 12:27:54.431  1573  3519 D BtGatt.GattService: registerClient(com.cleanproject) - UUID=31e09b9f-c264-41ea-bdd8-b17c8a835759
12-04 12:27:54.433  1573  3519 D BtGatt.ContextMap: add() - appUid: 10303, appPid: 18420, appName: com.cleanproject
12-04 12:27:54.435  1573  1672 D BtGatt.GattService: onClientRegistered() - UUID=31e09b9f-c264-41ea-bdd8-b17c8a835759, clientIf=9
12-04 12:27:54.436 18420 18808 D BluetoothGatt: onClientRegistered() - status=0 clientIf=9
12-04 12:27:54.443  1573  3519 D BtGatt.GattService: clientConnect(com.cleanproject) - address = FEEBA9_8, isDirect=true transport =2 set own addr = false own addr type:0, clientIf: 9, opportunistic=false, phy: 7
12-04 12:27:54.444  1573  2347 W bt_btm  : BTM_SecAddBleDevice: dev_type=0x2
12-04 12:27:54.444  1573  2347 E bt_stack: [ERROR:gatt_api.cc(1237)] GATT_Connectgatt_if=9, address=fe:eb:a9:02:1b:78, is_direct=1, opportunistic=0
12-04 12:27:54.445  1573  2347 I bt_stack: [INFO:gatt_attr.cc(888)] gatt_sr_init_cl_status: bda=fe:eb:a9:02:1b:78, cl_supp_feat=0000, aware=1
12-04 12:27:54.445  1573  2347 W bt_btm  : btm_ble_disable_resolving_list() rl_state = 0x0, rl_mask = 0x1, to_resume = 1
12-04 12:27:54.580  1129  1129 I GestureDetector: handleMessage TAP
12-04 12:27:54.580  1129  1154 I GestureDetector: handleMessage TAP
12-04 12:27:54.902   760   798 D BatteryDump: wait_for_battery_event : occurred : change@/devices/platform/samsung_mobile_device/samsung_mobile_device:battery/power_supply/battery 
12-04 12:27:54.906   760   760 I android.hardware.health@2.1-service-samsung: updateLrpSysfs: write: 292
12-04 12:27:54.954   820   820 I SurfaceFlinger: SFWD update time=54861089575760
12-04 12:27:55.214  1129  1479 D NetdEventListenerService: DNS Requested by : 100, 10303, 0
12-04 12:27:55.810   368   368 D io_stats: !@ 179,0 r 509958 15388139 w 192676 6511972 d 41720 6263184 f 0 0 iot 252256 0 th 0 0 0 pt 0 inp 0 0 54861.945
12-04 12:27:57.104  1129  2164 D SamsungAlarmManager: Cancel Alarm calling from uid:10179 pid :15801 / OP:PendingIntent{866a8f5: PendingIntentRecord{2fd805e com.google.android.gms/ startService}}
12-04 12:27:57.106  1129  2164 V SamsungAlarmManager: setLocked to kernel - W:54947402 / NW:54866135, now=54863241
12-04 12:27:57.110  1129  2164 D SamsungAlarmManager: Cancel Alarm calling from uid:10179 pid :2269 / OP:PendingIntent{daec68a: PendingIntentRecord{48a490c com.google.android.gms/ startService}}
12-04 12:27:57.111  1129  2164 V SamsungAlarmManager: setLocked to kernel - W:54947402 / NW:54866135, now=54863246
12-04 12:27:57.242  1129  1479 D NetdEventListenerService: DNS Requested by : 100, 10303, 0
12-04 12:27:57.281  1129  1183 D PowerManagerService: UserActivityStateListenerState: 0
12-04 12:27:57.514  1506  1506 I wpa_supplicant: Heartbeat 5468
12-04 12:27:59.260  1129  1479 D NetdEventListenerService: DNS Requested by : 100, 10303, 0
12-04 12:27:59.446  1573  2347 I bt_stack: [INFO:gatt_attr.cc(342)] gatt_connect_cback: remove untrusted client status, bda=fe:eb:a9:02:1b:78
12-04 12:27:59.447  1573  2347 W bt_stack: [WARNING:bta_gattc_act.cc(384)] bta_gattc_open_fail: Cannot establish Connection. conn_id=000000. Return GATT_ERROR(133)
12-04 12:27:59.454  1573  2347 W bt_btm  : btm_ble_disable_resolving_list() rl_state = 0x0, rl_mask = 0x1, to_resume = 1
12-04 12:27:59.455  1573  1672 D BtGatt.GattService: onConnected() - clientIf=9, connId=0, status=133, address=FEEBA9_8
12-04 12:27:59.456 18420 18808 D BluetoothGatt: onClientConnectionState() - status=133 clientIf=9 device=FE:EB:A9:02:1B:78
12-04 12:27:59.463 18420 18420 D ReactNativeBleManager: onConnectionStateChange to 0 on peripheral: FE:EB:A9:02:1B:78 with status 133
12-04 12:27:59.464 18420 18420 D BluetoothGatt: close()
12-04 12:27:59.473 18420 18420 D BluetoothGatt: unregisterApp() - mClientIf=9
12-04 12:27:59.476  1573  3519 D BtGatt.GattService: unregisterClient(com.cleanproject) - clientIf=9
12-04 12:27:59.478  1573  3519 D BtGatt.ContextMap: remove() - id: 9
12-04 12:27:59.478  1573  3519 E BtGatt.ContextMap: remove() - removed: 9
12-04 12:27:59.479  1573  2347 I bt_stack: [INFO:gatt_api.cc(1102)] GATT_Deregister gatt_if=9
12-04 12:27:59.479  1573  2347 I bt_stack: [INFO:gatt_api.cc(1155)] Initialize tGATT_REG
12-04 12:27:59.480 18420 18420 D BluetoothGatt: cancelOpen() - device: FE:EB:A9:02:1B:78
12-04 12:27:59.480 18420 18420 D BluetoothGatt: close()
12-04 12:27:59.482 18420 18550 I ReactNativeJS: 'Connection error', 'Connection error'
12-04 12:27:59.485 18420 18420 D BluetoothGatt: unregisterApp() - mClientIf=0
12-04 12:27:59.488 18420 18420 D ReactNativeBleManager: Peripheral event (BleManagerDisconnectPeripheral):FE:EB:A9:02:1B:78
12-04 12:27:59.488 18420 18420 D ReactNativeBleManager: Disconnect
12-04 12:27:59.489 18420 18550 I ReactNativeJS: Ok
12-04 12:27:59.555 18420 18550 I ReactNativeJS: Disconnected from FE:EB:A9:02:1B:78
12-04 12:28:00.000  1129  1250 D SamsungAlarmManager: Expired : 8
@philips77
Copy link
Member

Could you paste here the code relevant to how you connect to the device?
What error do you get? Does it work on other devices? Can you connect to your device using nRF Connect app from Google Play?

@dan-developer
Copy link
Author

dan-developer commented Dec 8, 2022

Yes.

On build.gradle:

implementation 'no.nordicsemi.android.support.v18:scanner:1.6.0'
implementation 'no.nordicsemi.android:ble:2.6.0-alpha04'

On DanScanManager.java:

@Override
public void scan(ReadableArray serviceUUIDs, final int scanSeconds, ReadableMap options,  Callback callback) {
    // Scanning settings
    final ScanSettings settings = new ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setReportDelay(0)
            .setUseHardwareBatchingIfSupported(false)
            .build();

    final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
    scanner.startScan(null, settings, mScanCallback);

    if (scanSeconds > 0) {
        Thread thread = new Thread() {
            private int currentScanSession = scanSessionId.incrementAndGet();

            @Override
            public void run() {

                try {
                    Thread.sleep(scanSeconds * 1000);
                } catch (InterruptedException ignored) {
                }

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        BluetoothAdapter btAdapter = getBluetoothAdapter();
                        // check current scan session was not stopped
                        if (scanSessionId.intValue() == currentScanSession) {
                            if(btAdapter.getState() == BluetoothAdapter.STATE_ON) {
                                scanner.stopScan(mScanCallback);
                            }
                            WritableMap map = Arguments.createMap();
                            bleManager.sendEvent("BleManagerStopScan", map);
                        }
                    }
                });

            }

        };
        thread.start();
    }
    callback.invoke();
}

private ScanCallback mScanCallback = new ScanCallback() {
    public void onScanResult(final int callbackType, @NonNull final ScanResult result) {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.i(bleManager.LOG_TAG, "DiscoverPeripheral: " + result.getDevice().getName());

                DanPeripheral peripheral = (DanPeripheral) bleManager.getPeripheral(result.getDevice());
                if (peripheral == null) {
                    peripheral = new DanPeripheral(bleManager.getReactContext(), result);
                } else {
                    peripheral.updateData(result);
                    peripheral.updateRssi(result.getRssi());
                }
                bleManager.savePeripheral(peripheral);

                WritableMap map = peripheral.asWritableMap();
                bleManager.sendEvent("BleManagerDiscoverPeripheral", map);
            }
        });
    }

    public void onBatchScanResults(@NonNull final List<no.nordicsemi.android.support.v18.scanner.ScanResult> results) {
    }

    @Override
    public void onScanFailed(final int errorCode) {
        WritableMap map = Arguments.createMap();
        bleManager.sendEvent("BleManagerStopScan", map);
    }
};

On Peripheral.java:

public void connect(Callback callback, Activity activity) {
    if (!connected) {
        BluetoothDevice device = getDevice();
        this.connectCallback = callback;
        this.connecting = true;
        Handler handler = new Handler(Looper.getMainLooper());
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
            Log.d(BleManager.LOG_TAG, "connectGatt(activity, false, this, BluetoothDevice.TRANSPORT_LE, PhyRequest.PHY_LE_1M_MASK | PhyRequest.PHY_LE_2M_MASK | PhyRequest.PHY_LE_CODED_MASK, handler)");
            gatt = device.connectGatt(activity, false, this,
                    BluetoothDevice.TRANSPORT_LE, 1 | 1 << 1 | 1 << 2, handler);
        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
            // A variant of connectGatt with Handled can't be used here.
            // Check https://github.com/NordicSemiconductor/Android-BLE-Library/issues/54
            // This bug specifically occurs in SDK 26 and is fixed in SDK 27
            Log.d(BleManager.LOG_TAG, "connectGatt(activity, false, this, BluetoothDevice.TRANSPORT_LE, PhyRequest.PHY_LE_1M_MASK | PhyRequest.PHY_LE_2M_MASK | PhyRequest.PHY_LE_CODED_MASK)");
            gatt = device.connectGatt(activity, false, this,
                    BluetoothDevice.TRANSPORT_LE, 1 | 1 << 1 | 1 << 2/*, handler*/);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Log.d(BleManager.LOG_TAG, "connectGatt(activity, false, this, BluetoothDevice.TRANSPORT_LE)");
            gatt = device.connectGatt(activity, false, this,
                    BluetoothDevice.TRANSPORT_LE);
        } else {
            Log.d(BleManager.LOG_TAG, "connectGatt(activity, false, this)");
            gatt = device.connectGatt(activity, false, this);
        }
    } else {
        if (gatt != null) {
            callback.invoke();
        } else {
            callback.invoke("BluetoothGatt is null");
        }
    }
}

@philips77
Copy link
Member

I see you're not using the BLE library, just the native API directly with some code copied from here. Is it because it didn't work for you?

Did you try connecting with just PHY_LE_1M_MASK, not all 3?

@dan-developer
Copy link
Author

Sorry...

Follow the code using Android-BLE-Library.

Peripheral.java:

...

public class Peripheral extends BluetoothGattCallback {

	...

	public Peripheral(BluetoothDevice device, int advertisingRSSI, byte[] scanRecord, ReactContext reactContext) {
		this.device = device;
		this.bufferedCharacteristics = new HashMap<String, NotifyBufferContainer>();
		this.advertisingRSSI = advertisingRSSI;
		this.advertisingDataBytes = scanRecord;
		this.danBleManager = new DanBleManager(reactContext);
		this.reactContext = reactContext;
	}

	...

	public void connect(Callback callback, Activity activity) {
		if (!connected) {
			BluetoothDevice device = getDevice();
			this.connectCallback = callback;
			this.connecting = true;
				/* called when the request is about to be executed */
				this.danBleManager.connect(this.device)
						// Automatic retries are supported, in case of 133 error.
						.retry(3 /* times, with */, 100 /* ms interval */)
						// A connection timeout can be set. This is additional to the Android's connection timeout which is 30 seconds.
						.timeout(15_000 /* ms */)
						// The auto connect feature from connectGatt is available as well
						.useAutoConnect(true)
						// This API can be set on any Android version, but will only be used on devices running Android 8+ with
						// support to the selected PHY.
						.usePreferredPhy(PhyRequest.PHY_LE_1M_MASK | PhyRequest.PHY_LE_2M_MASK | PhyRequest.PHY_LE_CODED_MASK)
						// A connection timeout can be also set. This is additional to the Android's connection timeout which is 30 seconds.
						.timeout(15_000 /* ms */)
						.then(result -> { Log.d(BleManager.LOG_TAG, "Finished connect to device: " + this.device.getAddress());sendConnectionEvent(device, "BleManagerConnectPeripheral", BluetoothGatt.GATT_SUCCESS);Callback.invoke(); /* called when the request was finished with either success, or a failure */ })
						.fail(new FailCallback() {
							@Override
							public void onRequestFailed(@NonNull BluetoothDevice device, int status) {
								Log.d(BleManager.LOG_TAG, "Failed to connect to: " + device.getAddress() + " with status " + status);
								sendConnectionEvent(device, "BleManagerDisconnectPeripheral", BluetoothGatt.GATT_FAILURE);
								callback.invoke("Connection error.");
							}
						})
						// Each request must be enqueued.
						// Kotlin projects can use suspend() or suspendForResult() instead.
						// Java projects can also use await() which is blocking.
						.enqueue();

		} else {
			if (connected) {
				callback.invoke();
			} else {
				callback.invoke("BluetoothGatt is null");
			}
		}
	}
	...

}

@philips77
Copy link
Member

From the log you posted in the first message it looks like you're getting error 133. This is a generic error, which doesn't say much.

What you may try:

  1. Check without
.usePreferredPhy(PhyRequest.PHY_LE_1M_MASK | PhyRequest.PHY_LE_2M_MASK | PhyRequest.PHY_LE_CODED_MASK)
  1. Check if you can connect to that device using nRF Connect app.
  2. Try connecting to your device from another phone.
  3. As this is not really an issue with the BLE library, but either with the phone or your device, try asking this question on DevZone, where you can also get help regarding the fw. They may ask you to get sniffer logs, etc.

@minghuadev
Copy link

Hi, I have a question in a similar setup. So we use the blinky example, but modified values of the service uuid and chars to connect to a Nordic NUS peripheral. The blinky calls into this Android-BLE-Library. I've tracked the logcat output, it's making call using only 1M for phy, like:

            gatt = device.connectGatt(context, false, callback,
                    BluetoothDevice.TRANSPORT_LE, PhyRequest.PHY_LE_1M_MASK, handler);

The question is, in the output of HCI snoop log, it enables both the 2M and Coded phy:

Command Opcode: LE Extended Create Connection (0x2043)
......
Initiating PHYs: 0x7, LE Coded, LE 2M, LE 1M
   0000 0... = Reserved: 0x00
   .... .1.. = LE Coded: True
   .... ..1. = LE 2M: True
   .... ...1 = LE 1M: True

Is this normal or a bug somewhere in the Android library or stack? Is there a way to disable the 2M and Coded bits on this HCI command, where to change the code? I hope there is a way to fix it on the Android side, or at least we know better about it. At the same time, we are also looking into the peripheral side.

When using sniffer, I can see the LL_FEATURE_REQ are having coded-phy and 2M bits set. I'm assuming if we change the "LE Extended Create Connection" command parameter on HCI, it may fix the problem. The problem happens on multiple recent phones and tablets using Mediatek chipsets.

Any comments or hints will be appreciated.

Thanks.

@philips77
Copy link
Member

From our experience Android completely ignores "preferred PHY" and knows better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants