hypfvieh / dbus-java

Improved version of java DBus library provided by freedesktop.org (https://dbus.freedesktop.org/doc/dbus-java/)
https://hypfvieh.github.io/dbus-java/
MIT License
185 stars 73 forks source link

Register Advertisment Options #109

Closed r-t-s closed 4 years ago

r-t-s commented 4 years ago

Not sure what are valid "OPTIONS" for the registration. When I try (I have also tried null, but get null pointer exception):

          mBTAdvertisement = new BTAdvertisement();
          mBTAdvertisement.Build();
          ap = new  DBusPath(mBTAdvertisement.getObjectPath());
          LEAdvertisingManager1 advm = sDBus.getRemoteObject("org.bluez", "/org/bluez", LEAdvertisingManager1.class);
          Map<String, Variant<?>> opts = new HashMap<String, Variant<?>>();
          advm.RegisterAdvertisement(ap, opts);

I get the following exception:

org.freedesktop.dbus.errors.UnknownMethod: Method "RegisterAdvertisement" with signature "oa{sv}" on interface "org.bluez.LEAdvertisingManager1" does\
n't exist
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
        at org.freedesktop.dbus.errors.Error.getException(Error.java:157)
        at org.freedesktop.dbus.errors.Error.throwException(Error.java:187)
        at org.freedesktop.dbus.RemoteInvocationHandler.executeRemoteMethod(RemoteInvocationHandler.java:164)
        at org.freedesktop.dbus.RemoteInvocationHandler.invoke(RemoteInvocationHandler.java:228)
        at com.sun.proxy.$Proxy24.RegisterAdvertisement(Unknown Source)
        at com.rtsservices.gc.BTHandler.<init>(BTHandler.java:124)

For reference: my Class Code (Started from Python Example ... plan to customize when I get it working!)

  class BTAdvertisement implements LEAdvertisement1 {
        private final String TAG = "BTHandler.AdvertiseMent1";

        Map<String, Variant<?>> mProperties = new HashMap<String, Variant<?>>();
        List<String> mServiceUUIDs = new ArrayList<String>();
        Map<UInt16, Variant<byte[]>> mManufacturerData = new HashMap<UInt16, Variant<byte[]>>();
        Map<String, Variant<byte[]>> mServiceData = new HashMap<String, Variant<byte[]>>();
        Map<Byte, Variant<byte[]>> mData = new HashMap<Byte, Variant<byte[]>>();
        String mLocalName;
        boolean mIncludeTXPower = true;

        @Override
        public boolean isRemote() {
          PersistLog.i(TAG, "isRemote");
          return mIncludeTXPower;
        }

        @Override
        public String getObjectPath() {
          PersistLog.i(TAG, "getObjectPath");
          return "/opensesame/advertisment";
        }

        @Override
        public <A> A Get(String interface_name, String property_name) {
          PersistLog.i(TAG, "Get");
          return null;
        }

        @Override
        public <A> void Set(String interface_name, String property_name, A value) {
          PersistLog.i(TAG, "Set");
        }

        @Override
        public Map<String, Variant<?>> GetAll(String interface_name) {
          PersistLog.i(TAG, "GetAll");
          return Properties();
        }

        @Override
        public void Release() {
          PersistLog.i(TAG, "Release");
        }

        public void AddServiceUUID(String uuid) {
          mServiceUUIDs.add(uuid);
        }

        public void AddManufacturerData(UInt16 Code, byte[]Data) {
          mManufacturerData.put(Code, new Variant<byte[]>(Data));
        }

        public void AddServiceData(String uuid, byte[]Data) {
          mServiceData.put(uuid,  new Variant<byte[]>(Data));
        }

        public void AddLocalName(String name) {
          mLocalName = name;
        }

        public void IncludeTXPower(boolean State) {
          mIncludeTXPower = State;
        }

        public void AddData(byte id, byte[] Data) {
          mData.put(id, new Variant<byte[]>(Data));
        }

        public Map<String, Variant<?>> Properties() {
                HashMap<String, Variant<?>> props = new HashMap<String, Variant<?>>();
                mProperties.put("Type", new Variant<String>("peripheral"));
                if (mServiceUUIDs.size() > 0) {
                        mProperties.put("ServiceUUIDs", new Variant<List<String>>(mServiceUUIDs));
                }
                if (mManufacturerData.size() > 0) {
                        mProperties.put("ManufacturerData", new Variant<Map<UInt16, Variant<byte[]>>>(mManufacturerData));
                }
                if (mServiceData.size() > 0) {
                        mProperties.put("ServiceData", new Variant<Map<String, Variant<byte[]>>>(mServiceData));
                }
                if (mLocalName != null) {
                        mProperties.put("LocalName", new Variant<String>(mLocalName));
                }
                mProperties.put("IncludeTXPower", new Variant<Boolean>(mIncludeTXPower));
                if (mData.size() > 0) {
                        mProperties.put("Data", new Variant<Map<Byte, Variant<byte[]>>>(mData));
                }
                props.put("", new Variant<Map<String, Variant<?>>>(mProperties));;
                return props;
        }

        // Ultimately this will be in a subclass
        public void Build() {
          AddServiceUUID("180D");
          AddServiceUUID("180F");
          UInt16 code = new UInt16(0xffff);
          byte[] data = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04};
          AddManufacturerData(code, data);
          AddServiceData("9999", data);
          AddLocalName("RaspberryGate");
          data = new byte[] {0x03, 0x02, 0x01, 0x00};
          byte id = 0x26;
          AddData(id, data);
        }
    }
hypfvieh commented 4 years ago

You have to gather the LEAdvertisingManager1 on the bluetooth adapter you are using. So change the code:

LEAdvertisingManager1 advm = sDBus.getRemoteObject("org.bluez", "/org/bluez", LEAdvertisingManager1.class);

to:

LEAdvertisingManager1 advm = sDBus.getRemoteObject("org.bluez", "/org/bluez/hci0", LEAdvertisingManager1.class);

Note the second parameter! If your adapter is not called hci0, change it to the name of your adapter.

A quick note on the "options". I did not use LEAdvertisingManager1 before, but after reading the C++ code from bluez commandline client, I think that the properties listed here (or in the javadoc of LEAdvertisement1 interface class) are the supported options.

The bluez commandline client defines the options in a struct in the file, line 63 client/advertising.c