@@ -2,19 +2,20 @@ package gatt
2
2
3
3
import (
4
4
"encoding/binary"
5
+ "fmt"
5
6
"log"
6
7
"sync"
7
8
8
- "github.com/currantlabs/ble/linux/att"
9
9
"github.com/currantlabs/ble"
10
+ "github.com/currantlabs/ble/linux/att"
10
11
)
11
12
12
13
const (
13
14
cccNotify = 0x0001
14
15
cccIndicate = 0x0002
15
16
)
16
17
17
- // NewClient .. .
18
+ // NewClient returns a GATT Client .
18
19
func NewClient (conn ble.Conn ) (* Client , error ) {
19
20
p := & Client {
20
21
subs : make (map [uint16 ]* sub ),
@@ -25,48 +26,77 @@ func NewClient(conn ble.Conn) (*Client, error) {
25
26
return p , nil
26
27
}
27
28
28
- // Client .. .
29
+ // A Client is a GATT Client .
29
30
type Client struct {
30
31
sync.RWMutex
31
32
32
- svcs [] * ble.Service
33
- name string
34
- subs map [uint16 ]* sub
33
+ profile * ble.Profile
34
+ name string
35
+ subs map [uint16 ]* sub
35
36
36
37
ac * att.Client
37
38
conn ble.Conn
38
39
}
39
40
40
- // Address .. .
41
+ // Address returns the address of the client .
41
42
func (p * Client ) Address () ble.Addr {
42
43
p .RLock ()
43
44
defer p .RUnlock ()
44
45
return p .conn .RemoteAddr ()
45
46
}
46
47
47
- // Name .. .
48
+ // Name returns the name of the client .
48
49
func (p * Client ) Name () string {
49
50
p .RLock ()
50
51
defer p .RUnlock ()
51
52
return p .name
52
53
}
53
54
54
- // Services .. .
55
- func (p * Client ) Services () [] * ble.Service {
55
+ // Profile returns the discovered profile .
56
+ func (p * Client ) Profile () * ble.Profile {
56
57
p .RLock ()
57
58
defer p .RUnlock ()
58
- return p .svcs
59
+ return p .profile
60
+ }
61
+
62
+ // DiscoverProfile discovers the whole hierachy of a server.
63
+ func (p * Client ) DiscoverProfile (force bool ) (* ble.Profile , error ) {
64
+ if p .profile != nil && ! force {
65
+ return p .profile , nil
66
+ }
67
+ ss , err := p .DiscoverServices (nil )
68
+ if err != nil {
69
+ return nil , fmt .Errorf ("can't discover services: %s\n " , err )
70
+ }
71
+ for _ , s := range ss {
72
+ cs , err := p .DiscoverCharacteristics (nil , s )
73
+ if err != nil {
74
+ return nil , fmt .Errorf ("can't discover characteristics: %s\n " , err )
75
+ }
76
+ for _ , c := range cs {
77
+ _ , err := p .DiscoverDescriptors (nil , c )
78
+ if err != nil {
79
+ return nil , fmt .Errorf ("can't discover descriptors: %s\n " , err )
80
+ }
81
+ }
82
+ }
83
+ p .profile = & ble.Profile {Services : ss }
84
+ return p .profile , nil
59
85
}
60
86
61
- // DiscoverServices ...
87
+ // DiscoverServices finds all the primary services on a server. [Vol 3, Part G, 4.4.1]
88
+ // If filter is specified, only filtered services are returned.
62
89
func (p * Client ) DiscoverServices (filter []ble.UUID ) ([]* ble.Service , error ) {
63
90
p .Lock ()
64
91
defer p .Unlock ()
92
+ if p .profile == nil {
93
+ p .profile = & ble.Profile {}
94
+ }
65
95
start := uint16 (0x0001 )
66
96
for {
67
97
length , b , err := p .ac .ReadByGroupType (start , 0xFFFF , ble .PrimaryServiceUUID )
68
98
if err == ble .ErrAttrNotFound {
69
- return p .svcs , nil
99
+ return p .profile . Services , nil
70
100
}
71
101
if err != nil {
72
102
return nil , err
@@ -81,25 +111,27 @@ func (p *Client) DiscoverServices(filter []ble.UUID) ([]*ble.Service, error) {
81
111
Handle : h ,
82
112
EndHandle : endh ,
83
113
}
84
- p .svcs = append (p .svcs , s )
114
+ p .profile . Services = append (p .profile . Services , s )
85
115
}
86
116
if endh == 0xFFFF {
87
- return p .svcs , nil
117
+ return p .profile . Services , nil
88
118
}
89
119
start = endh + 1
90
120
b = b [length :]
91
121
}
92
122
}
93
123
}
94
124
95
- // DiscoverIncludedServices ...
125
+ // DiscoverIncludedServices finds the included services of a service. [Vol 3, Part G, 4.5.1]
126
+ // If filter is specified, only filtered services are returned.
96
127
func (p * Client ) DiscoverIncludedServices (ss []ble.UUID , s * ble.Service ) ([]* ble.Service , error ) {
97
128
p .Lock ()
98
129
defer p .Unlock ()
99
130
return nil , nil
100
131
}
101
132
102
- // DiscoverCharacteristics ...
133
+ // DiscoverCharacteristics finds all the characteristics within a service. [Vol 3, Part G, 4.6.1]
134
+ // If filter is specified, only filtered characteristics are returned.
103
135
func (p * Client ) DiscoverCharacteristics (filter []ble.UUID , s * ble.Service ) ([]* ble.Characteristic , error ) {
104
136
p .Lock ()
105
137
defer p .Unlock ()
@@ -138,7 +170,8 @@ func (p *Client) DiscoverCharacteristics(filter []ble.UUID, s *ble.Service) ([]*
138
170
return s .Characteristics , nil
139
171
}
140
172
141
- // DiscoverDescriptors ...
173
+ // DiscoverDescriptors finds all the descriptors within a characteristic. [Vol 3, Part G, 4.7.1]
174
+ // If filter is specified, only filtered descriptors are returned.
142
175
func (p * Client ) DiscoverDescriptors (filter []ble.UUID , c * ble.Characteristic ) ([]* ble.Descriptor , error ) {
143
176
p .Lock ()
144
177
defer p .Unlock ()
@@ -171,21 +204,21 @@ func (p *Client) DiscoverDescriptors(filter []ble.UUID, c *ble.Characteristic) (
171
204
return c .Descriptors , nil
172
205
}
173
206
174
- // ReadCharacteristic ...
207
+ // ReadCharacteristic reads a characteristic value from a server. [Vol 3, Part G, 4.8.1]
175
208
func (p * Client ) ReadCharacteristic (c * ble.Characteristic ) ([]byte , error ) {
176
209
p .Lock ()
177
210
defer p .Unlock ()
178
211
return p .ac .Read (c .ValueHandle )
179
212
}
180
213
181
- // ReadLongCharacteristic ...
214
+ // ReadLongCharacteristic reads a characteristic value which is longer than the MTU. [Vol 3, Part G, 4.8.3]
182
215
func (p * Client ) ReadLongCharacteristic (c * ble.Characteristic ) ([]byte , error ) {
183
216
p .Lock ()
184
217
defer p .Unlock ()
185
218
return nil , nil
186
219
}
187
220
188
- // WriteCharacteristic ...
221
+ // WriteCharacteristic writes a characteristic value to a server. [Vol 3, Part G, 4.9.3]
189
222
func (p * Client ) WriteCharacteristic (c * ble.Characteristic , v []byte , noRsp bool ) error {
190
223
p .Lock ()
191
224
defer p .Unlock ()
@@ -196,21 +229,21 @@ func (p *Client) WriteCharacteristic(c *ble.Characteristic, v []byte, noRsp bool
196
229
return p .ac .Write (c .ValueHandle , v )
197
230
}
198
231
199
- // ReadDescriptor ...
232
+ // ReadDescriptor reads a characteristic descriptor from a server. [Vol 3, Part G, 4.12.1]
200
233
func (p * Client ) ReadDescriptor (d * ble.Descriptor ) ([]byte , error ) {
201
234
p .Lock ()
202
235
defer p .Unlock ()
203
236
return p .ac .Read (d .Handle )
204
237
}
205
238
206
- // WriteDescriptor ...
239
+ // WriteDescriptor writes a characteristic descriptor to a server. [Vol 3, Part G, 4.12.3]
207
240
func (p * Client ) WriteDescriptor (d * ble.Descriptor , v []byte ) error {
208
241
p .Lock ()
209
242
defer p .Unlock ()
210
243
return p .ac .Write (d .Handle , v )
211
244
}
212
245
213
- // ReadRSSI ...
246
+ // ReadRSSI retrieves the current RSSI value of remote peripheral. [Vol 2, Part E, 7.5.4]
214
247
func (p * Client ) ReadRSSI () int {
215
248
p .Lock ()
216
249
defer p .Unlock ()
@@ -226,7 +259,8 @@ func (p *Client) ExchangeMTU(mtu int) (int, error) {
226
259
return p .ac .ExchangeMTU (mtu )
227
260
}
228
261
229
- // Subscribe ...
262
+ // Subscribe subscribes to indication (if ind is set true), or notification of a
263
+ // characteristic value. [Vol 3, Part G, 4.10 & 4.11]
230
264
func (p * Client ) Subscribe (c * ble.Characteristic , ind bool , h ble.NotificationHandler ) error {
231
265
p .Lock ()
232
266
defer p .Unlock ()
@@ -236,7 +270,8 @@ func (p *Client) Subscribe(c *ble.Characteristic, ind bool, h ble.NotificationHa
236
270
return p .setHandlers (c .CCCD .Handle , c .ValueHandle , cccNotify , h )
237
271
}
238
272
239
- // Unsubscribe ...
273
+ // Unsubscribe unsubscribes to indication (if ind is set true), or notification
274
+ // of a specified characteristic value. [Vol 3, Part G, 4.10 & 4.11]
240
275
func (p * Client ) Unsubscribe (c * ble.Characteristic , ind bool ) error {
241
276
p .Lock ()
242
277
defer p .Unlock ()
@@ -273,7 +308,7 @@ func (p *Client) setHandlers(cccdh, vh, flag uint16, h ble.NotificationHandler)
273
308
return p .ac .Write (s .cccdh , v )
274
309
}
275
310
276
- // ClearSubscriptions .. .
311
+ // ClearSubscriptions clears all subscriptions to notifications and indications .
277
312
func (p * Client ) ClearSubscriptions () error {
278
313
p .Lock ()
279
314
defer p .Unlock ()
0 commit comments