forked from muka/go-bluetooth
/
advertisement.go
140 lines (110 loc) · 2.92 KB
/
advertisement.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package api
import (
"fmt"
"github.com/godbus/dbus"
"github.com/muka/go-bluetooth/bluez"
"github.com/muka/go-bluetooth/bluez/profile/advertising"
log "github.com/sirupsen/logrus"
)
const baseAdvertismentPath = "/org/bluez/%s/apps/advertisement%d"
var advertisingCount int = -1
func nextAdvertismentPath(adapterID string) dbus.ObjectPath {
advertisingCount++
return dbus.ObjectPath(fmt.Sprintf(baseAdvertismentPath, adapterID, advertisingCount))
}
func decreaseAdvertismentCounter() {
advertisingCount--
if advertisingCount < -1 {
advertisingCount = -1
}
}
type Advertisement struct {
path dbus.ObjectPath
objectManager *DBusObjectManager
iprops *DBusProperties
conn *dbus.Conn
props *advertising.LEAdvertisement1Properties
}
func (a *Advertisement) DBusConn() *dbus.Conn {
return a.conn
}
func (a *Advertisement) DBusObjectManager() *DBusObjectManager {
return a.objectManager
}
func (a *Advertisement) DBusProperties() *DBusProperties {
return a.iprops
}
func (a *Advertisement) GetProperties() bluez.Properties {
return a.props
}
func (a *Advertisement) Path() dbus.ObjectPath {
return a.path
}
func (a *Advertisement) Interface() string {
return advertising.LEAdvertisement1Interface
}
func NewAdvertisement(adapterID string, props *advertising.LEAdvertisement1Properties) (*Advertisement, error) {
adv := new(Advertisement)
adv.props = props
adv.path = nextAdvertismentPath(adapterID)
conn, err := dbus.SystemBus()
if err != nil {
return nil, err
}
adv.conn = conn
om, err := NewDBusObjectManager(conn)
if err != nil {
return nil, err
}
adv.objectManager = om
iprops, err := NewDBusProperties(conn)
if err != nil {
return nil, err
}
adv.iprops = iprops
return adv, nil
}
// Expose to bluez an advertisment instance via the adapter advertisement manager
func ExposeAdvertisement(adapterID string, props *advertising.LEAdvertisement1Properties, discoverableTimeout uint32) (func(), error) {
log.Tracef("Retrieving adapter instance %s", adapterID)
a, err := GetAdapter(adapterID)
if err != nil {
return nil, err
}
adv, err := NewAdvertisement(adapterID, props)
if err != nil {
return nil, err
}
err = ExposeDBusService(adv)
if err != nil {
return nil, err
}
log.Debug("Setup adapter")
err = a.SetDiscoverable(true)
if err != nil {
return nil, err
}
err = a.SetDiscoverableTimeout(discoverableTimeout)
if err != nil {
return nil, err
}
err = a.SetPowered(true)
if err != nil {
return nil, err
}
log.Trace("Registering LEAdvertisement1 instance")
advManager, err := advertising.NewLEAdvertisingManager1FromAdapterID(adapterID)
if err != nil {
return nil, err
}
err = advManager.RegisterAdvertisement(adv.Path(), map[string]interface{}{})
if err != nil {
return nil, err
}
cancel := func() {
decreaseAdvertismentCounter()
advManager.UnregisterAdvertisement(adv.Path())
a.SetProperty("Discoverable", false)
}
return cancel, nil
}