c1114ad708
Signed-off-by: Ron Evans <ron@hybridgroup.com>
84 lines
2 KiB
Go
84 lines
2 KiB
Go
package bluetooth
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/JuulLabs-OSS/cbgo"
|
|
)
|
|
|
|
// Address contains a Bluetooth address, which is a MAC address plus some extra
|
|
// information.
|
|
type Address struct {
|
|
// UUID if this is macOS.
|
|
UUID
|
|
|
|
isRandom bool
|
|
}
|
|
|
|
// IsRandom if the address is randomly created.
|
|
func (ad Address) IsRandom() bool {
|
|
return ad.isRandom
|
|
}
|
|
|
|
// SetRandom if is a random address.
|
|
func (ad Address) SetRandom(val bool) {
|
|
ad.isRandom = val
|
|
}
|
|
|
|
// Set the address
|
|
func (ad Address) Set(val interface{}) {
|
|
ad.UUID = val.(UUID)
|
|
}
|
|
|
|
// 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 callback == nil {
|
|
return errors.New("must provide callback to Scan function")
|
|
}
|
|
|
|
if a.cancelChan != nil {
|
|
return errors.New("already calling Scan function")
|
|
}
|
|
|
|
a.peripheralFoundHandler = callback
|
|
|
|
// Channel that will be closed when the scan is stopped.
|
|
// Detecting whether the scan is stopped can be done by doing a non-blocking
|
|
// read from it. If it succeeds, the scan is stopped.
|
|
cancelChan := make(chan struct{})
|
|
a.cancelChan = cancelChan
|
|
|
|
a.cm.Scan(nil, &cbgo.CentralManagerScanOpts{
|
|
AllowDuplicates: true,
|
|
})
|
|
|
|
for {
|
|
// Check whether the scan is stopped. This is necessary to avoid a race
|
|
// condition between the signal channel and the cancelScan channel when
|
|
// the callback calls StopScan() (no new callbacks may be called after
|
|
// StopScan is called).
|
|
select {
|
|
case <-cancelChan:
|
|
// stop scanning here?
|
|
return nil
|
|
default:
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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.cancelChan != nil {
|
|
return errors.New("already calling Scan function")
|
|
}
|
|
|
|
a.cm.StopScan()
|
|
close(a.cancelChan)
|
|
a.cancelChan = nil
|
|
|
|
return nil
|
|
}
|