-
Notifications
You must be signed in to change notification settings - Fork 14
/
device.go
131 lines (111 loc) · 3.07 KB
/
device.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
package ble
import (
"fmt"
"log"
"net"
"strings"
)
const (
deviceInterface = "org.bluez.Device1"
interfacesAdded = "org.freedesktop.DBus.ObjectManager.InterfacesAdded"
)
// The Device type corresponds to the org.bluez.Device1 interface.
// See bluez/doc/devicet-api.txt
type Device interface {
BaseObject
Address() Address
AddressType() string
UUIDs() []string
Connected() bool
Paired() bool
Connect() error
Disconnect() error
Pair() error
}
func (conn *Connection) matchDevice(matching predicate) (Device, error) {
return conn.findObject(deviceInterface, matching)
}
// ValidAddress checks whether addr is a valid MAC address.
func ValidAddress(addr string) bool {
_, err := net.ParseMAC(addr)
return err == nil
}
// GetDeviceByAddress finds a Device in the object cache with the given address.
func (conn *Connection) GetDeviceByAddress(address Address) (Device, error) {
addr := Address(strings.ToUpper(string(address)))
device, err := conn.matchDevice(func(device *blob) bool {
return device.Address() == addr
})
if err != nil {
err = fmt.Errorf("%w with address %s", err, addr)
}
return device, err
}
// GetDeviceByName finds a Device in the object cache with the given name.
func (conn *Connection) GetDeviceByName(name string) (Device, error) {
device, err := conn.matchDevice(func(device *blob) bool {
return device.Name() == name
})
if err != nil {
err = fmt.Errorf("%w with name %q", err, name)
}
return device, err
}
// GetDeviceByUUID finds a Device in the object cache matching the given UUIDs.
func (conn *Connection) GetDeviceByUUID(uuids ...string) (Device, error) {
device, err := conn.matchDevice(func(device *blob) bool {
return UUIDsInclude(device.UUIDs(), uuids)
})
if err != nil {
err = fmt.Errorf("%w with UUIDs %v", err, uuids)
}
return device, err
}
// UUIDsInclude tests whether the advertised UUIDs contain all of the ones in uuids.
func UUIDsInclude(advertised []string, uuids []string) bool {
for _, u := range uuids {
if !ValidUUID(u) {
log.Printf("invalid UUID %s", u)
return false
}
if !stringsContain(advertised, LongUUID(u)) {
return false
}
}
return true
}
func (device *blob) Address() Address {
return Address(device.properties["Address"].Value().(string))
}
func (device *blob) AddressType() string {
return device.properties["AddressType"].Value().(string)
}
func (device *blob) UUIDs() []string {
return device.properties["UUIDs"].Value().([]string)
}
func (device *blob) Connected() bool {
return device.properties["Connected"].Value().(bool)
}
func (device *blob) Paired() bool {
return device.properties["Paired"].Value().(bool)
}
func (device *blob) Connect() error {
log.Printf("%s: connecting", device.Name())
return device.call("Connect")
}
func (device *blob) Disconnect() error {
log.Printf("%s: disconnecting", device.Name())
return device.call("Disconnect")
}
func (device *blob) Pair() error {
log.Printf("%s: pairing", device.Name())
return device.call("Pair")
}
func stringsContain(a []string, str string) bool {
for _, s := range a {
if s == str {
return true
}
}
return false
}