Skip to content

Commit d775214

Browse files
aykevldeadprogram
authored andcommitted
linux: rewrite everything to use DBus directly
This is a big rewrite to use DBus calls directly instead of going through go-bluetooth first. This is a big change, but I believe it is an improvement. While the go-bluetooth works for many cases, it's a layer in between that I believe hurts more than it helps. Without it, we can just program directly against the BlueZ D-Bus API. The end result is about 10% more code. With this rewrite, I fixed the following issues: * All MapToStruct warnings are gone, like in #193. * Advertisements can be restarted after they were stopped. Previously this resulted in a panic. * Looking at the source code of go-bluetooth, it appears that it includes devices from a different Bluetooth adapter than the one that's currently scanning. This is fixed with the rewrite. * Fix a bug in Adapter.AddService where it would only allow adding a single service. Multiple services can now be added. This was actually the motivating bug that led me down to rewrite the whole thing because I couldn't figure out where the bug was in go-bluetooth (it's many layers deep). * The `WriteEvent` callback in a characteristic now also gets the 'offset' parameter which wasn't provided by go-bluetooth. This rewrite also avoids go-bluetooth specific workarounds like #74 and #121. I have tested all examples in the smoketest-linux Makefile target. They all still work with this rewrite.
1 parent b278e2b commit d775214

File tree

7 files changed

+368
-337
lines changed

7 files changed

+368
-337
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func must(action string, err error) {
106106

107107
## Linux
108108

109-
Go Bluetooth support for Linux uses [BlueZ](http://www.bluez.org/) via the [D-Bus](https://en.wikipedia.org/wiki/D-Bus) interface thanks to the https://github.com/muka/go-bluetooth package. This should work with most distros that support BlueZ such as Ubuntu, Debian, Fedora, and Arch Linux, among others.
109+
Go Bluetooth support for Linux uses [BlueZ](http://www.bluez.org/) via the [D-Bus](https://en.wikipedia.org/wiki/D-Bus) interface. This should work with most distros that support BlueZ such as Ubuntu, Debian, Fedora, and Arch Linux, among others.
110110

111111
Linux can be used both as a BLE Central or as a BLE Peripheral.
112112

adapter_linux.go

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,20 @@ package bluetooth
77

88
import (
99
"errors"
10+
"fmt"
1011

11-
"github.com/muka/go-bluetooth/api"
12-
"github.com/muka/go-bluetooth/bluez/profile/adapter"
12+
"github.com/godbus/dbus/v5"
1313
)
1414

15+
const defaultAdapter = "hci0"
16+
1517
type Adapter struct {
16-
adapter *adapter.Adapter1
1718
id string
18-
cancelChan chan struct{}
19+
scanCancelChan chan struct{}
20+
bus *dbus.Conn
21+
bluez dbus.BusObject // object at /
22+
adapter dbus.BusObject // object at /org/bluez/hciX
23+
address string
1924
defaultAdvertisement *Advertisement
2025

2126
connectHandler func(device Address, connected bool)
@@ -26,29 +31,38 @@ type Adapter struct {
2631
//
2732
// Make sure to call Enable() before using it to initialize the adapter.
2833
var DefaultAdapter = &Adapter{
34+
id: defaultAdapter,
2935
connectHandler: func(device Address, connected bool) {
30-
return
3136
},
3237
}
3338

3439
// Enable configures the BLE stack. It must be called before any
3540
// Bluetooth-related calls (unless otherwise indicated).
3641
func (a *Adapter) Enable() (err error) {
37-
if a.id == "" {
38-
a.adapter, err = api.GetDefaultAdapter()
39-
if err != nil {
40-
return
42+
bus, err := dbus.SystemBus()
43+
if err != nil {
44+
return err
45+
}
46+
a.bus = bus
47+
a.bluez = a.bus.Object("org.bluez", dbus.ObjectPath("/"))
48+
a.adapter = a.bus.Object("org.bluez", dbus.ObjectPath("/org/bluez/"+a.id))
49+
addr, err := a.adapter.GetProperty("org.bluez.Adapter1.Address")
50+
if err != nil {
51+
if err, ok := err.(dbus.Error); ok && err.Name == "org.freedesktop.DBus.Error.UnknownObject" {
52+
return fmt.Errorf("bluetooth: adapter %s does not exist", a.adapter.Path())
4153
}
42-
a.id, err = a.adapter.GetAdapterID()
54+
return fmt.Errorf("could not activate BlueZ adapter: %w", err)
4355
}
56+
addr.Store(&a.address)
57+
4458
return nil
4559
}
4660

4761
func (a *Adapter) Address() (MACAddress, error) {
48-
if a.adapter == nil {
62+
if a.address == "" {
4963
return MACAddress{}, errors.New("adapter not enabled")
5064
}
51-
mac, err := ParseMAC(a.adapter.Properties.Address)
65+
mac, err := ParseMAC(a.address)
5266
if err != nil {
5367
return MACAddress{}, err
5468
}

0 commit comments

Comments
 (0)