11package bluetooth
22
33import (
4+ "context"
45 "errors"
56 "time"
67
@@ -15,6 +16,19 @@ import (
1516// Passing a nil slice of UUIDs will return a complete list of
1617// services.
1718func (d Device ) DiscoverServices (uuids []UUID ) ([]DeviceService , error ) {
19+ ctx , cancel := context .WithTimeoutCause (context .Background (), 10 * time .Second , errors .New ("timeout on DiscoverServices" ))
20+ defer cancel ()
21+ return d .DiscoverServicesWithContext (ctx , uuids )
22+ }
23+
24+ // DiscoverServicesWithContext starts a service discovery procedure. Pass a list of service
25+ // UUIDs you are interested in to this function. Either a slice of all services
26+ // is returned (of the same length as the requested UUIDs and in the same
27+ // order), or if some services could not be discovered an error is returned.
28+ //
29+ // Passing a nil slice of UUIDs will return a complete list of
30+ // services.
31+ func (d Device ) DiscoverServicesWithContext (ctx context.Context , uuids []UUID ) ([]DeviceService , error ) {
1832 d .prph .DiscoverServices ([]cbgo.UUID {})
1933
2034 // clear cache of services
@@ -52,8 +66,8 @@ func (d Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
5266 d .services [svc .uuidWrapper ] = svc
5367 }
5468 return svcs , nil
55- case <- time . NewTimer ( 10 * time . Second ). C :
56- return nil , errors . New ( "timeout on DiscoverServices" )
69+ case <- ctx . Done () :
70+ return nil , ctx . Err ( )
5771 }
5872}
5973
@@ -90,6 +104,21 @@ func (s DeviceService) UUID() UUID {
90104// Passing a nil slice of UUIDs will return a complete list of
91105// characteristics.
92106func (s DeviceService ) DiscoverCharacteristics (uuids []UUID ) ([]DeviceCharacteristic , error ) {
107+ ctx , cancel := context .WithTimeoutCause (context .Background (), 10 * time .Second , errors .New ("timeout on DiscoverCharacteristics" ))
108+ defer cancel ()
109+ return s .DiscoverCharacteristicsWithContext (ctx , uuids )
110+ }
111+
112+ // DiscoverCharacteristicsWithContext discovers characteristics in this service. Pass a
113+ // list of characteristic UUIDs you are interested in to this function. Either a
114+ // list of all requested services is returned, or if some services could not be
115+ // discovered an error is returned. If there is no error, the characteristics
116+ // slice has the same length as the UUID slice with characteristics in the same
117+ // order in the slice as in the requested UUID list.
118+ //
119+ // Passing a nil slice of UUIDs will return a complete list of
120+ // characteristics.
121+ func (s DeviceService ) DiscoverCharacteristicsWithContext (ctx context.Context , uuids []UUID ) ([]DeviceCharacteristic , error ) {
93122 cbuuids := []cbgo.UUID {}
94123
95124 s .device .prph .DiscoverCharacteristics (cbuuids , s .service )
@@ -136,8 +165,8 @@ func (s DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacteri
136165 }
137166 }
138167 return chars , nil
139- case <- time . NewTimer ( 10 * time . Second ). C :
140- return nil , errors . New ( "timeout on DiscoverCharacteristics" )
168+ case <- ctx . Done () :
169+ return nil , ctx . Err ( )
141170 }
142171}
143172
@@ -179,13 +208,21 @@ func (c DeviceCharacteristic) UUID() UUID {
179208// Write replaces the characteristic value with a new value. The
180209// call will return after all data has been written.
181210func (c DeviceCharacteristic ) Write (p []byte ) (n int , err error ) {
211+ ctx , cancel := context .WithTimeoutCause (context .Background (), 10 * time .Second , errors .New ("timeout on Write()" ))
212+ defer cancel ()
213+ return c .WriteWithContext (ctx , p )
214+ }
215+
216+ // WriteWithContext replaces the characteristic value with a new value. The
217+ // call will return after all data has been written.
218+ func (c DeviceCharacteristic ) WriteWithContext (ctx context.Context , p []byte ) (n int , err error ) {
182219 c .writeChan = make (chan error )
183220 c .service .device .prph .WriteCharacteristic (p , c .characteristic , true )
184221
185222 // wait for result
186223 select {
187- case <- time . NewTimer ( 10 * time . Second ). C :
188- err = errors . New ( "timeout on Write()" )
224+ case <- ctx . Done () :
225+ err = ctx . Err ( )
189226 case err = <- c .writeChan :
190227 }
191228
@@ -229,6 +266,13 @@ func (c DeviceCharacteristic) GetMTU() (uint16, error) {
229266
230267// Read reads the current characteristic value.
231268func (c * deviceCharacteristic ) Read (data []byte ) (n int , err error ) {
269+ ctx , cancel := context .WithTimeoutCause (context .Background (), 10 * time .Second , errors .New ("timeout on Read()" ))
270+ defer cancel ()
271+ return c .ReadWithContext (ctx , data )
272+ }
273+
274+ // ReadWithContext reads the current characteristic value.
275+ func (c * deviceCharacteristic ) ReadWithContext (ctx context.Context , data []byte ) (n int , err error ) {
232276 c .readChan = make (chan error )
233277 c .service .device .prph .ReadCharacteristic (c .characteristic )
234278
@@ -239,9 +283,9 @@ func (c *deviceCharacteristic) Read(data []byte) (n int, err error) {
239283 if err != nil {
240284 return 0 , err
241285 }
242- case <- time . NewTimer ( 10 * time . Second ). C :
286+ case <- ctx . Done () :
243287 c .readChan = nil
244- return 0 , errors . New ( "timeout on Read()" )
288+ return 0 , ctx . Err ( )
245289 }
246290
247291 copy (data , c .characteristic .Value ())
0 commit comments