inthehand / 32feet

Personal Area Networking for .NET. Open source and professionally supported
https://inthehand.com/components/32feet/
MIT License
818 stars 206 forks source link

Can pair to device, but cannot connect to it. What am I missing? #264

Closed FifthCloud closed 1 year ago

FifthCloud commented 1 year ago

I am really loving this software. There is something that I am missing and I feel I am close to the answer.

I have a Maui app that I am trying to connect to a Bluetooth device: BLE Device. It comes with an app that I am able to connect and pass data to and from it. When I am trying to make my own app I can pair it with it, but I am unable to get the device connected.

AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH"
                     android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
                     android:maxSdkVersion="30" />

    <!-- Needed only if your app looks for Bluetooth devices.
         If your app doesn't use Bluetooth scan results to derive physical
         location information, you can strongly assert that your app
         doesn't derive physical location. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

    <!-- Needed only if your app makes the device discoverable to Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <!-- Needed only if your app communicates with already-paired Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
</manifest>

Have added every single permission related to Bluetooth to make sure I didn't miss anything.

My function where I call the Bluetooth connection

public async Task<bool> BluetoothConnection()
    {
        bluetoothDevicePicker = new BluetoothDevicePicker();
        deviceInfo = await bluetoothDevicePicker.PickSingleDeviceAsync();

        if (deviceInfo == null)
        {
            OnConsoleMessages?.Invoke("Bluetooth Picker came back null. Why?"); // This is my own public event where I see these messages.
            return false;
        }

        OnConsoleMessages?.Invoke("Device has been selected. Attempting to connect.");

        // In the Hand had this. So I am testing this out as well.
        await Task.Delay(2000);

        System.Guid guid1 = new System.Guid(SspUdid1); // See comment below to see what GUID1 and GUID2 are.
        System.Guid guid2 = new System.Guid(SspUdid2);

        bool paired = BluetoothSecurity.PairRequest(deviceInfo.DeviceAddress, "0000"); // Returns true!
        OnConsoleMessages?.Invoke($"Pairing request is {paired}");
        await Task.Delay(2000);

        bluetoothClient.Connect(deviceInfo.DeviceAddress, BluetoothService.SerialPort); // Takes about 30 seconds but always says not connected. Even if I try guid1 or guid2.

        // I have this here to try using my own GUIDs that I found
        // Using my own Windows 11 machine I was able to look at the Gatt profiles and found the following
        // GUIDs associated with this device.
        /*
        0: "1800" (Service) // Is this even valid guids?
        1: "1801" (Service) // Is this even valid guids?
        2: "00001530-1212-efde-1523-785feabcd123" (Service) // This is the value from variable is guid1
        3: "180A" (Service) // Is this even valid guids?
        4: "6e400001-b5a3-f393-e0a9-e50e24dcca9e" (Service) // This is the value from variable is guid2
        */
        //bluetoothClient.Connect(deviceInfo.DeviceAddress, /*BluetoothService.SerialPort*/ guid1);  

        if (!bluetoothClient.Connected) // bluetoothClient.Connected always returns false :(
        {
            OnConsoleMessages?.Invoke($"Pairing was unsuccessful. Pair Request: {paired} & Connected: {bluetoothClient.Connected}");

            return false;
        }
        OnConsoleMessages?.Invoke($"Connection is successful!");
        return true;
    }

From all the research I have been doing about Bluetooth permissions, I think it's normal I don't get any pop-ups stating if I want to accept Bluetooth permission. Not sure why I cannot connect. Does anyone have any insight? Feel as though I am really close.

peterfoot commented 1 year ago

It looks like you are using the Bluetooth Classic library and trying to connect to Bluetooth Low Energy services. For that you need to use the InTheHand.BluetoothLE library.

FifthCloud commented 1 year ago

Thanks for the help so far. Have updated the code to the following...

public async Task<IReadOnlyList<GattCharacteristic>> BLETest()
    {
        bluetoothDevice = null;
        if(await Bluetooth.GetAvailabilityAsync()) // Always returns true;
        {
            RequestDeviceOptions requestDeviceOptions = new()
            {
                AcceptAllDevices = true
            };
            var devs = await Bluetooth.ScanForDevicesAsync(requestDeviceOptions); // with or without "requestDeviceOptions" returns 0 scan devices
            // No matter what I do ScanForDevices doesn't return anything. 

            if (devs.Count == 0)
            {
                OnConsoleMessages?.Invoke("Scan came up empty. Nothing found.");
                return null;
            }
            // .....
}

dev.Count always returns 0. What am I missing? Isn't await Bluetooth.ScanForDevicesAsync(requestDeviceOptions); this line of code a BLE function. According to the documentation it is stating this is BLE functionality.

Peter, what I am missing? Really trying to figure this out on my own, but I am such a beginner I am stumbling here and there.

FifthCloud commented 1 year ago

Yeah, I was really close. The answer was this.

 RequestDeviceOptions requestDeviceOptions = new()
            {
                AcceptAllDevices = true
            };

            var requestDevice = await Bluetooth.RequestDeviceAsync(requestDeviceOptions);

Was able to select the BLE device and see all the Gatt profiles. Appreciate the nudge in the right direction.