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 141 142 143 144 145 146 147
|
package api
import (
"fmt"
"github.com/godbus/dbus/v5"
"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"
const BaseAdvertismentPath = "/go_bluetooth/%s/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()
err := advManager.UnregisterAdvertisement(adv.Path())
if err != nil {
log.Warn(err)
}
err = a.SetProperty("Discoverable", false)
if err != nil {
log.Warn(err)
}
}
return cancel, nil
}
|