macos: able to retrieve some of the info when scanning

Signed-off-by: Ron Evans <ron@hybridgroup.com>
This commit is contained in:
Ron Evans 2020-08-28 08:35:13 +02:00
parent 51b2b4c2b2
commit a620bacdb8
5 changed files with 138 additions and 70 deletions

View file

@ -2,22 +2,109 @@ package bluetooth
import (
"github.com/JuulLabs-OSS/cbgo"
"github.com/tinygo-org/bluetooth/macbt"
)
type Adapter struct {
cm cbgo.CentralManager
cmd macbt.CMDelegate
cbgo.CentralManagerDelegateBase
cbgo.PeripheralManagerDelegateBase
cm cbgo.CentralManager
pm cbgo.PeripheralManager
peripheralFoundHandler func(*Adapter, ScanResult)
cancelChan chan struct{}
}
// DefaultAdapter is the default adapter on the system.
//
// Make sure to call Enable() before using it to initialize the adapter.
var DefaultAdapter = &Adapter{}
var DefaultAdapter = &Adapter{
cm: cbgo.NewCentralManager(nil),
pm: cbgo.NewPeripheralManager(nil),
}
// Enable configures the BLE stack. It must be called before any
// Bluetooth-related calls (unless otherwise indicated).
func (a *Adapter) Enable() error {
a.cm = cbgo.NewCentralManager(nil)
a.cm.SetDelegate(a)
// TODO: wait until powered
a.pm.SetDelegate(a)
// TODO: wait until powered
return nil
}
// CentralManager delegate functions
func (a *Adapter) CentralManagerDidUpdateState(cmgr cbgo.CentralManager) {
}
// DidDiscoverPeripheral when peripheral is discovered.
func (a *Adapter) DidDiscoverPeripheral(cmgr cbgo.CentralManager, prph cbgo.Peripheral,
advFields cbgo.AdvFields, rssi int) {
if a.peripheralFoundHandler != nil {
sr := makeScanResult(prph, advFields, rssi)
a.peripheralFoundHandler(a, sr)
}
}
// DidConnectPeripheral when peripheral is connected.
func (a *Adapter) DidConnectPeripheral(cmgr cbgo.CentralManager, prph cbgo.Peripheral) {
}
// DidDisconnectPeripheral when peripheral is disconnected.
func (a *Adapter) DidDisconnectPeripheral(cmgr cbgo.CentralManager, prph cbgo.Peripheral, err error) {
}
// PeripheralManager delegate functions
// PeripheralManagerDidUpdateState when state updated.
func (a *Adapter) PeripheralManagerDidUpdateState(pmgr cbgo.PeripheralManager) {
}
// DidAddService when service added.
func (a *Adapter) DidAddService(pmgr cbgo.PeripheralManager, svc cbgo.Service, err error) {
}
// DidStartAdvertising when advertising starts.
func (a *Adapter) DidStartAdvertising(pmgr cbgo.PeripheralManager, err error) {
}
// DidReceiveReadRequest when read request received.
func (a *Adapter) DidReceiveReadRequest(pmgr cbgo.PeripheralManager, cbreq cbgo.ATTRequest) {
}
// DidReceiveWriteRequests when write requests received.
func (a *Adapter) DidReceiveWriteRequests(pmgr cbgo.PeripheralManager, cbreqs []cbgo.ATTRequest) {
}
// CentralDidSubscribe when central subscribed.
func (a *Adapter) CentralDidSubscribe(pmgr cbgo.PeripheralManager, cent cbgo.Central, cbchr cbgo.Characteristic) {
}
// CentralDidUnsubscribe when central unsubscribed.
func (a *Adapter) CentralDidUnsubscribe(pmgr cbgo.PeripheralManager, cent cbgo.Central, chr cbgo.Characteristic) {
}
// makeScanResult creates a ScanResult when peripheral is found.
func makeScanResult(prph cbgo.Peripheral, advFields cbgo.AdvFields, rssi int) ScanResult {
// TODO: figure out the peripheral info.
// TODO: create a list of serviceUUIDs.
return ScanResult{
RSSI: int16(rssi),
Address: Address{
// TODO: fill in this info
//MAC: prph.Identifier(),
//IsRandom: prph.Identifier == "random",
},
AdvertisementPayload: &advertisementFields{
AdvertisementFields{
LocalName: advFields.LocalName,
// TODO: fill in this info
//ServiceUUIDs: serviceUUIDs,
},
},
}
}

View file

@ -1,14 +1,59 @@
package bluetooth
import (
"errors"
"github.com/JuulLabs-OSS/cbgo"
)
// 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) {
return nil
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
}

View file

@ -1,27 +0,0 @@
// Implements the CentralManagerDelegate interface. CoreBluetooth
// communicates events asynchronously via callbacks. This file implements a
// synchronous interface by translating these callbacks into channel
// operations.
package macbt
import (
"github.com/JuulLabs-OSS/cbgo"
)
// CMDelegate to handle callbacks from CoreBluetooth.
type CMDelegate struct {
}
func (d *CMDelegate) CentralManagerDidUpdateState(cmgr cbgo.CentralManager) {
}
func (d *CMDelegate) DidDiscoverPeripheral(cmgr cbgo.CentralManager, prph cbgo.Peripheral,
advFields cbgo.AdvFields, rssi int) {
}
func (d *CMDelegate) DidConnectPeripheral(cmgr cbgo.CentralManager, prph cbgo.Peripheral) {
}
func (d *CMDelegate) DidDisconnectPeripheral(cmgr cbgo.CentralManager, prph cbgo.Peripheral, err error) {
}

View file

@ -1,2 +0,0 @@
// Package macbt is wrapper to CoreBluetooth.
package macbt

View file

@ -1,35 +0,0 @@
// Implements the PeripheralManagerDelegate interface.
// CoreBluetooth communicates events asynchronously via callbacks. This file
// implements a synchronous interface by translating these callbacks into
// channel operations.
package macbt
import (
"github.com/JuulLabs-OSS/cbgo"
)
// PMDelegate to handle callbacks from CoreBluetooth.
type PMDelegate struct {
}
func (d *PMDelegate) PeripheralManagerDidUpdateState(pmgr cbgo.PeripheralManager) {
}
func (d *PMDelegate) DidAddService(pmgr cbgo.PeripheralManager, svc cbgo.Service, err error) {
}
func (d *PMDelegate) DidStartAdvertising(pmgr cbgo.PeripheralManager, err error) {
}
func (d *PMDelegate) DidReceiveReadRequest(pmgr cbgo.PeripheralManager, cbreq cbgo.ATTRequest) {
}
func (d *PMDelegate) DidReceiveWriteRequests(pmgr cbgo.PeripheralManager, cbreqs []cbgo.ATTRequest) {
}
func (d *PMDelegate) CentralDidSubscribe(pmgr cbgo.PeripheralManager, cent cbgo.Central, cbchr cbgo.Characteristic) {
}
func (d *PMDelegate) CentralDidUnsubscribe(pmgr cbgo.PeripheralManager, cent cbgo.Central, chr cbgo.Characteristic) {
}