1
votes

I'm very new to DBUS and BlueZ. I've been following several guides up to the point where I'm required to create an LEAdvertisement1 interface and register it with LEAdvertisingManager1.

I've been reading the BlueZ documentation for LEAdvertisement1:

Service     org.bluez
Interface   org.bluez.LEAdvertisement1
Object path freely definable

I'm not sure what is meant by the object path being freely definable. I tried to follow the BlueZ example (using dbus-next instead of python) but I keep running into the error "org.bluez.Error.Failed" when I run RegisterAdvertisement. The error wasn't providing any useful information so to troubleshoot I ran the dbus monitor.

sudo dbus-monitor --system "destination='org.bluez'" "sender='org.bluez'"

Within the monitor I was receiving the following error:

method call time=1622421524.320548 sender=:1.18 -> destination=org.freedesktop.DBus serial=71 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "type='signal',sender=':1.37',path='/org/bluez/example/advertisement0',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',arg0='org.bluez.LEAdvertisement1'"
method return time=1622421524.320650 sender=org.freedesktop.DBus -> destination=:1.18 serial=35 reply_serial=71
method call time=1622421524.322726 sender=:1.18 -> destination=org.freedesktop.DBus serial=72 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=StartServiceByName
   string ":1.37"
   uint32 0
error time=1622421524.322852 sender=org.freedesktop.DBus -> destination=:1.18 error_name=org.freedesktop.DBus.Error.ServiceUnknown reply_serial=72
   string "The name :1.37 was not provided by any .service files" 

Interface Class:

const LE_ADVERTISEMENT_IFACE = 'org.bluez.LEAdvertisement1';
const PATH_BASE = '/org/bluez/example/advertisement';

export class BLEAdvertisementInterface extends dbus.interface.Interface {
    adType: string = "peripheral";
    serviceUuids: Array<any> = [];
    manufacturerData: any; //none
    solicitUuids: Array<any> = []; //none
    serviceData: any; //none
    localName: string = "Testing";
    includeTxPower: boolean = false;
    data: any; //none

    constructor() {
        super(LE_ADVERTISEMENT_IFACE);
        this.serviceUuids = [uuidv4()];
    }

    @method({ inSignature: "s", outSignature: "a{sv}" })
    GetAll(): Variant {
        console.log("This does not run due to service unknown error");
        let includes = [];
        if(this.includeTxPower) includes.push("tx-power");
        const allProperties = {
            LocalName: new Variant("s", this.localName),
            ServiceUUIDs: new Variant("as", this.serviceUuids),
            Includes: new Variant("as",includes),
            Type: new Variant("s", this.adType)
        };
        return new Variant("a{sv}", allProperties);
    }

    @method({ inSignature: "", outSignature: "" })
    Release() {
        console.log("released!");
    }
}

Adapter Code (not sure if I even need requestName):

let advertisement = new BLEAdvertisementInterface();
this.getAdvertisingManager().RegisterAdvertisement("/org/bluez/example/advertisement0", {}).then((result: any) => {
  console.log(result)
}, (err: any) => {
  console.log(err);
});

I'm not sure exactly what I'm missing. I tried several things such as requestName and export. As well as checking the security settings under system.d. I feel like there is some configuration I need to do within Linux (raspbian) to get this working but I'm not sure where. Any assistance anyone can give me into figuring out the next step will be greatly appreciated. Most online guides seem to gloss over this step and reference a library. Sadly they're all in python.

BlueZ Documentation: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/advertising-api.txt

BlueZ Example: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-advertisement

dbus-next: https://github.com/dbusjs/node-dbus-next

Thanks

1

1 Answers

1
votes

To create an advertisement in BlueZ with the DBus API there are two things that need to happen. The first is that you create a DBus service with the interface org.bluez.LEAdvertisement1 and the second is to tell BlueZ where that service is with RegisterAdvertisement.

From the error message you posted in your question it looks like BlueZ cannot find the service that is at /org/bluez/example/advertisement0.

I have little experience with node-js, but having a quick browser of the documentation for node-dbus-next it looks like you need

bus.export('/org/bluez/example/advertisement0', advertisement)

to publish the DBus service you have defined.

On the command line if you do a busctl list you should be able to see a new service has appeared even if you don't do the second step of RegisterAdvertisement. The service will have a unique name (i.e. :x.xxx) without using request name. You will not be able to do much with the service because of security settings but it will prove you are publishing something. The next step is to register the service with BlueZ. It is at that stage that you are likely to see Failed to parse advertisement errors if the format of the advertisement is not what BlueZ is expecting.