prototooth/gap_darwin.go
2020-09-02 08:37:04 +02:00

84 lines
2.0 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
}