-
Notifications
You must be signed in to change notification settings - Fork 140
/
gap_windows.go
84 lines (75 loc) · 2.29 KB
/
gap_windows.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
package bluetooth
import (
"tinygo.org/x/bluetooth/winbt"
)
// Address contains a Bluetooth MAC address.
type Address struct {
MACAddress
}
// Scan starts a BLE scan. It is stopped by a call to StopScan. A common pattern
// is to cancel the scan when a particular device has been found.
func (a *Adapter) Scan(callback func(*Adapter, ScanResult)) (err error) {
if a.watcher != nil {
// Cannot scan more than once: which one should ScanStop()
// stop?
return errScanning
}
a.watcher, err = winbt.NewBluetoothLEAdvertisementWatcher()
if err != nil {
return
}
defer a.watcher.Release()
// Listen for incoming BLE advertisement packets.
err = a.watcher.AddReceivedEvent(func(watcher *winbt.IBluetoothLEAdvertisementWatcher, args *winbt.IBluetoothLEAdvertisementReceivedEventArgs) {
var result ScanResult
result.RSSI = args.RawSignalStrengthInDBm()
addr := args.BluetoothAddress()
adr := result.Address.(Address)
for i := range adr.MAC {
adr.MAC[i] = byte(addr)
addr >>= 8
}
// Note: the IsRandom bit is never set.
advertisement := args.Advertisement()
result.AdvertisementPayload = &advertisementFields{
AdvertisementFields{
LocalName: advertisement.LocalName(),
},
}
callback(a, result)
})
if err != nil {
return
}
// Wait for when advertisement has stopped by a call to StopScan().
// Advertisement doesn't seem to stop right away, there is an
// intermediate Stopping state.
stoppingChan := make(chan struct{})
err = a.watcher.AddStoppedEvent(func(watcher *winbt.IBluetoothLEAdvertisementWatcher, args *winbt.IBluetoothLEAdvertisementWatcherStoppedEventArgs) {
// Note: the args parameter has an Error property that should
// probably be checked, but I'm not sure when stopping the
// advertisement watcher could ever result in an error (except
// for bugs).
close(stoppingChan)
})
if err != nil {
return
}
err = a.watcher.Start()
if err != nil {
return err
}
// Wait until advertisement has stopped, and finish.
<-stoppingChan
a.watcher = nil
return nil
}
// StopScan stops any in-progress scan. It can be called from within a Scan
// callback to stop the current scan. If no scan is in progress, an error will
// be returned.
func (a *Adapter) StopScan() error {
if a.watcher == nil {
return errNotScanning
}
return a.watcher.Stop()
}