hypfvieh / bluez-dbus

bluetooth library for linux OSes using DBus and bluez (http://www.bluez.org/).
MIT License
69 stars 20 forks source link

How to use this library for Bluetooth intermediate communication #56

Closed 1784450277 closed 1 year ago

1784450277 commented 1 year ago

How to use this library for Bluetooth intermediate communication

I have little contact with this area at ordinary times. I need this content in my recent work. I don't see any communication related code in the code. Could you please give me some advice? Thank you very much.

hypfvieh commented 1 year ago

This library provides the required interfaces to interact with Linux bluez bluetooth stack using DBus. There are some helper classes which are primarily designed to use with bluetooth low energy (BLE) devices (see DeviceManager).

There are some usage samples here: https://github.com/hypfvieh/sandbox/tree/master/src/main/java/com/github/hypfvieh/sandbox/bluez

or take a look at other projects utilizing bluez-dbus: https://github.com/hypfvieh/bluez-dbus/issues/25

1784450277 commented 1 year ago

I see that these codes depend on dbus-java-core, but the java version I use is 8. It seems that there is no 3. x version of dbus-java-core for me to reference. What should I do

hypfvieh commented 1 year ago

The latest currently available release in maven central is 0.1.4 which uses dbus-java 3.3 and is still compatible with Java 8. The upcoming release 0.2.0 will require at least Java 11 and will use dbus-java 4.x.

But anyways, I would highly recommend to stop using ancient no longer supported Java versions as they may contain bugs and/or security issues which will not be fixed.

1784450277 commented 1 year ago

Okay, I'll try

1784450277 commented 1 year ago

My Bluetooth device can't find any service after it is connected, but the mobile phone debugging tool can connect normally and see the corresponding uuid. Why? Can you help me see it? Thank you

public static void test() {
    DeviceManager manager;
    try {
        manager = DeviceManager.getInstance();
    } catch (IllegalStateException e) {
        System.out.println(StrUtil.format("caught - {}", e.toString()));
        try {
            manager = DeviceManager.createInstance(false);
        } catch (DBusException e1) {
            throw new IllegalStateException(e1);
        }
    }
    BluetoothDevice selectedDevice = null;
    for (BluetoothDevice device : manager.scanForBluetoothDevices("hci0", 5000)) {
        String deviceName = device.getName();
        System.out.println(StrUtil.format("[{}] {} {}", device.getAdapter().getDeviceName(), device.getAddress(), deviceName));
        if (deviceName.equals("53184500001")) {
            selectedDevice = device;
            break;
        }
    }
    if (Objects.isNull(selectedDevice)) {
        System.out.println("device no found");
        return;
    }
    boolean connect = selectedDevice.connect();
    System.out.println(connect);
    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(selectedDevice);
    selectedDevice.refreshGattServices();
    System.out.println(selectedDevice.getGattServices().size());
    for (BluetoothGattService service : selectedDevice.getGattServices()) {
        service.refreshGattCharacteristics();
        System.out.println(service.getGattCharacteristics().size());
        for (BluetoothGattCharacteristic characteristic : service.getGattCharacteristics()) {
            System.out.println(StrUtil.format("hci0 characteristic - {}", characteristic.getUuid()));
        }
    }
}
1784450277 commented 1 year ago

selectedDevice.getGattServices().size() = 0

hypfvieh commented 1 year ago

Please check if bluez/dbus is seeing the device and the services it provides correctly. You can check that using d-feet and something like blueman.

If you cannot see anything in d-feet or blueman, you will never see it when using bluez-dbus.

1784450277 commented 1 year ago

1678183351884_67C22888-83B3-492d-856D-C85A2242EF8A image

I can see the corresponding uuid directly in linux

hypfvieh commented 1 year ago

Do you see it when using d-feet?

1784450277 commented 1 year ago

I execute the program on nanopi. There is no operation interface and I can't use d-feet. Is there any other way

hypfvieh commented 1 year ago

This can also be done using dbus-send if you know the correct pathes. Usually when a device is discovered by bluez, it is added to the available pathes.

dbus-send --system --dest=org.bluez --type=method_call --print-reply / org.freedesktop.DBus.ObjectManager.GetManagedObjects

This should list all known pathes. The connected device should look like: "/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX"

1784450277 commented 1 year ago

method return time=1678189079.682823 sender=:1.31 -> destination=:1.71 serial=18253 reply_serial=2
   array [
      dict entry(
         object path "/org/bluez"
         array [
            dict entry(
               string "org.freedesktop.DBus.Introspectable"
               array [
               ]
            )
            dict entry(
               string "org.bluez.AgentManager1"
               array [
               ]
            )
            dict entry(
               string "org.bluez.ProfileManager1"
               array [
               ]
            )
            dict entry(
               string "org.bluez.Alert1"
               array [
               ]
            )
            dict entry(
               string "org.bluez.HealthManager1"
               array [
               ]
            )
         ]
      )
      dict entry(
         object path "/org/bluez/hci0"
         array [
            dict entry(
               string "org.freedesktop.DBus.Introspectable"
               array [
               ]
            )
            dict entry(
               string "org.bluez.Adapter1"
               array [
                  dict entry(
                     string "Address"
                     variant                         string "4E:3F:44:4E:4E:56"
                  )
                  dict entry(
                     string "Name"
                     variant                         string "NanoPi-M1-Plus"
                  )
                  dict entry(
                     string "Alias"
                     variant                         string "NanoPi-M1-Plus"
                  )
                  dict entry(
                     string "Class"
                     variant                         uint32 0
                  )
                  dict entry(
                     string "Powered"
                     variant                         boolean true
                  )
                  dict entry(
                     string "Discoverable"
                     variant                         boolean false
                  )
                  dict entry(
                     string "DiscoverableTimeout"
                     variant                         uint32 180
                  )
                  dict entry(
                     string "Pairable"
                     variant                         boolean true
                  )
                  dict entry(
                     string "PairableTimeout"
                     variant                         uint32 0
                  )
                  dict entry(
                     string "Discovering"
                     variant                         boolean false
                  )
                  dict entry(
                     string "UUIDs"
                     variant                         array [
                           string "00001801-0000-1000-8000-00805f9b34fb"
                           string "0000110e-0000-1000-8000-00805f9b34fb"
                           string "00001200-0000-1000-8000-00805f9b34fb"
                           string "00001800-0000-1000-8000-00805f9b34fb"
                           string "0000110c-0000-1000-8000-00805f9b34fb"
                        ]
                  )
                  dict entry(
                     string "Modalias"
                     variant                         string "usb:v1D6Bp0246d0525"
                  )
               ]
            )
            dict entry(
               string "org.freedesktop.DBus.Properties"
               array [
               ]
            )
            dict entry(
               string "org.bluez.Media1"
               array [
               ]
            )
            dict entry(
               string "org.bluez.CyclingSpeedManager1"
               array [
               ]
            )
            dict entry(
               string "org.bluez.HeartRateManager1"
               array [
               ]
            )
            dict entry(
               string "org.bluez.ThermometerManager1"
               array [
               ]
            )
            dict entry(
               string "org.bluez.NetworkServer1"
               array [
               ]
            )
         ]
      )
      dict entry(
         object path "/org/bluez/hci0/dev_C0_BF_19_42_74_BF"
         array [
            dict entry(
               string "org.freedesktop.DBus.Introspectable"
               array [
               ]
            )
            dict entry(
               string "org.bluez.Device1"
               array [
                  dict entry(
                     string "Address"
                     variant                         string "C0:BF:19:42:74:BF"
                  )
                  dict entry(
                     string "Name"
                     variant                         string "53184500001"
                  )
                  dict entry(
                     string "Alias"
                     variant                         string "53184500001"
                  )
                  dict entry(
                     string "Paired"
                     variant                         boolean false
                  )
                  dict entry(
                     string "Trusted"
                     variant                         boolean false
                  )
                  dict entry(
                     string "Blocked"
                     variant                         boolean false
                  )
                  dict entry(
                     string "LegacyPairing"
                     variant                         boolean false
                  )
                  dict entry(
                     string "Connected"
                     variant                         boolean false
                  )
                  dict entry(
                     string "UUIDs"
                     variant                         array [
                           string "00001800-0000-1000-8000-00805f9b34fb"
                           string "00001801-0000-1000-8000-00805f9b34fb"
                           string "0000fe59-0000-1000-8000-00805f9b34fb"
                           string "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
                        ]
                  )
                  dict entry(
                     string "Adapter"
                     variant                         object path "/org/bluez/hci0"
                  )
               ]
            )
            dict entry(
               string "org.freedesktop.DBus.Properties"
               array [
               ]
            )
            dict entry(
               string "org.bluez.ProximityReporter1"
               array [
                  dict entry(
                     string "LinkLossAlertLevel"
                     variant                         string "none"
                  )
                  dict entry(
                     string "ImmediateAlertLevel"
                     variant                         string "none"
                  )
               ]
            )
         ]
      )
   ]
1784450277 commented 1 year ago

Is this result normal

hypfvieh commented 1 year ago

This is the regular output. When you connect to the device C0:BF:19:42:74:BF there should be more data including the gatt services.

1784450277 commented 1 year ago

The output is the same after the connection

hypfvieh commented 1 year ago

Did you 'pair' the devices? After pairing, you should see something like this:

dict entry(
         object path "/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service002b"
         array [
            dict entry(
               string "org.freedesktop.DBus.Introspectable"
               array [
               ]
            )
            dict entry(
               string "org.bluez.GattService1"
               array [
                  dict entry(
                     string "UUID"
                     variant                         string "0000ffe0-0000-1000-8000-00805f9b34fb"
                  )
                  dict entry(
                     string "Device"
                     variant                         object path "/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX"
                  )
                  dict entry(
                     string "Primary"
                     variant                         boolean true
                  )
                  dict entry(
                     string "Includes"
                     variant                         array [
                        ]
                  )
               ]
            )

Which defines a GATT service. If you get this, you will also be able to access it using bluez-dbus. (be sure you call selectedDevice.pair() after connection is established and before querying for services, otherwise it will not work).

1784450277 commented 1 year ago

I don't see the GATT service, no pair. The devices I connect to don't need to be paired. They can be connected directly. The mobile phone Bluetooth debugging tool (nRF Connect) can connect to this device normally and send and receive data

hypfvieh commented 1 year ago

I know that this is usually not required when using BLE, but with bluez you have to:

From bluez documentation regard 'pair' method:

This method will connect to the remote device, initiate pairing and then retrieve all SDP records (or GATT primary services). If the application has registered its own agent, then that specific agent will be used. Otherwise it will use the default agent. Only for applications like a pairing wizard it would make sense to have its own agent. In almost all other cases the default agent will handle this just fine. In case there is no application agent and also no default agent present, this method will fail.

1784450277 commented 1 year ago

There will be errors when pair in the code


Exception in thread "main" org.freedesktop.dbus.exceptions.DBusExecutionException: Authentication Canceled
    at sun.reflect.GeneratedConstructorAccessor7.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.freedesktop.dbus.errors.Error.getException(Error.java:145)
    at org.freedesktop.dbus.errors.Error.throwException(Error.java:175)
    at org.freedesktop.dbus.RemoteInvocationHandler.executeRemoteMethod(RemoteInvocationHandler.java:152)
    at org.freedesktop.dbus.RemoteInvocationHandler.invoke(RemoteInvocationHandler.java:216)
    at com.sun.proxy.$Proxy21.Pair(Unknown Source)
    at com.github.hypfvieh.bluetooth.wrapper.BluetoothDevice.pair(BluetoothDevice.java:507)
    at org.ScanMain.test(ScanMain.java:66)
    at org.ScanMain.main(ScanMain.java:28)
1784450277 commented 1 year ago

I can successfully operate pair directly in Linux, but I still can't see the gatt service you said by using the previous command to view the data. It's painful

hypfvieh commented 1 year ago

I didn't invent bluez - but it is the bluetooth implementation used on Linux. It is not easy to use and often you need lots of trail and error.

I can't help you with your specific problem, because I don't know what device you want to use and I'm pretty sure that I also don't have the same device for testing. All I can tell is: when you don't see the GATT services on DBus, you cannot use them in bluez-dbus because DBus is the "glue" between Java and bluez.

1784450277 commented 1 year ago

Thank you very much for your patience. I have determined that it is a hardware problem. Now I can successfully obtain the gatt service