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
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.