Connect to peripherals by UUIDString. Eliminate globals for central
manager and delegate.
This commit is contained in:
parent
0424b70ef3
commit
c91c83de9c
115
ble_darwin.go
115
ble_darwin.go
|
@ -8,6 +8,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"git.wow.st/gmp/ble/ns"
|
"git.wow.st/gmp/ble/ns"
|
||||||
)
|
)
|
||||||
|
@ -22,22 +23,39 @@ type BLE struct {
|
||||||
|
|
||||||
ready, wantScan bool
|
ready, wantScan bool
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
|
cd *ns.CBDelegate
|
||||||
|
cm *ns.CBCentralManager
|
||||||
}
|
}
|
||||||
|
|
||||||
var ble *BLE
|
var cdLookup map[unsafe.Pointer] *BLE
|
||||||
|
var pdLookup map[unsafe.Pointer] *BLE
|
||||||
|
|
||||||
type State string
|
type State string
|
||||||
|
|
||||||
type Peripheral struct {
|
type Peripheral struct {
|
||||||
Name string
|
Name string
|
||||||
RSSI int
|
RSSI int
|
||||||
|
Identifier string
|
||||||
|
|
||||||
identifier *ns.NSUUID
|
|
||||||
p *ns.CBPeripheral
|
p *ns.CBPeripheral
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Peripheral) Identifier() string {
|
func peripheralName(p *ns.CBPeripheral) string {
|
||||||
return p.identifier.UUIDString().String()
|
var ret string
|
||||||
|
nsname := p.Name()
|
||||||
|
if nsname.Ptr() != nil {
|
||||||
|
ret = nsname.String()
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPeripheral(x *ns.CBPeripheral) Peripheral {
|
||||||
|
return Peripheral{
|
||||||
|
Name: peripheralName(x),
|
||||||
|
Identifier: x.Identifier().UUIDString().String(),
|
||||||
|
p: x,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type PeripheralListItem struct {
|
type PeripheralListItem struct {
|
||||||
|
@ -55,7 +73,7 @@ func (ps *Peripherals) Add(x Peripheral) bool {
|
||||||
defer ps.Unlock()
|
defer ps.Unlock()
|
||||||
found := false
|
found := false
|
||||||
for n,item := range ps.items {
|
for n,item := range ps.items {
|
||||||
if item.p.identifier.IsEqual(x.identifier) {
|
if item.p.Identifier == x.Identifier {
|
||||||
item.p = x
|
item.p = x
|
||||||
item.seen = time.Now()
|
item.seen = time.Now()
|
||||||
ps.items[n] = item
|
ps.items[n] = item
|
||||||
|
@ -118,7 +136,7 @@ func stringState(x ns.CBManagerState) string {
|
||||||
func (b *BLE) State() string {
|
func (b *BLE) State() string {
|
||||||
b.Lock()
|
b.Lock()
|
||||||
defer b.Unlock()
|
defer b.Unlock()
|
||||||
return stringState(ble.state)
|
return stringState(b.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BLE) setState(x ns.CBManagerState) {
|
func (b *BLE) setState(x ns.CBManagerState) {
|
||||||
|
@ -128,7 +146,7 @@ func (b *BLE) setState(x ns.CBManagerState) {
|
||||||
if b.ready && b.wantScan {
|
if b.ready && b.wantScan {
|
||||||
go func() {
|
go func() {
|
||||||
fmt.Printf("Go: Scanning\n")
|
fmt.Printf("Go: Scanning\n")
|
||||||
cm.ScanForPeripheralsWithServices(nil, nil)
|
b.cm.ScanForPeripheralsWithServices(nil, nil)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +159,7 @@ func (b *BLE) Scan() {
|
||||||
} else {
|
} else {
|
||||||
b.Unlock()
|
b.Unlock()
|
||||||
fmt.Printf("Go: Scanning\n")
|
fmt.Printf("Go: Scanning\n")
|
||||||
cm.ScanForPeripheralsWithServices(nil, nil)
|
b.cm.ScanForPeripheralsWithServices(nil, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +171,7 @@ func (b *BLE) StopScan() {
|
||||||
}
|
}
|
||||||
b.Unlock()
|
b.Unlock()
|
||||||
fmt.Printf("Go: stopping scan\n")
|
fmt.Printf("Go: stopping scan\n")
|
||||||
cm.StopScan()
|
b.cm.StopScan()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BLE) Connect(p Peripheral) {
|
func (b *BLE) Connect(p Peripheral) {
|
||||||
|
@ -163,13 +181,22 @@ func (b *BLE) Connect(p Peripheral) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b.Unlock()
|
b.Unlock()
|
||||||
cm.ConnectPeripheral(p.p, nil)
|
if p.p == nil {
|
||||||
|
ps := b.cm.RetrievePeripheralsWithIdentifiers(ns.NSArrayWithObjects(ns.NSUUIDAlloc().InitWithUUIDString(ns.NSStringWithGoString(p.Identifier))))
|
||||||
|
if (int)(ps.Count()) > 0 {
|
||||||
|
p.p = ps.ObjectAtIndex(0).CBPeripheral()
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.cm.ConnectPeripheral(p.p, nil)
|
||||||
fmt.Printf("cm.ConnectPeripheral() returned\n")
|
fmt.Printf("cm.ConnectPeripheral() returned\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateState(c *ns.CBCentralManager) {
|
func updateState(c *ns.CBCentralManager) {
|
||||||
|
ble := cdLookup[c.Ptr()]
|
||||||
fmt.Printf("Go: did update state\n")
|
fmt.Printf("Go: did update state\n")
|
||||||
st := cm.CBManager.State()
|
st := c.CBManager.State()
|
||||||
if st == (ns.CBManagerState)(ns.CBManagerStatePoweredOn) {
|
if st == (ns.CBManagerState)(ns.CBManagerStatePoweredOn) {
|
||||||
ble.ready = true
|
ble.ready = true
|
||||||
} else {
|
} else {
|
||||||
|
@ -179,57 +206,48 @@ func updateState(c *ns.CBCentralManager) {
|
||||||
ble.events <- UpdateStateEvent{State: stringState(st)}
|
ble.events <- UpdateStateEvent{State: stringState(st)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func peripheralName(p *ns.CBPeripheral) string {
|
|
||||||
var ret string
|
|
||||||
nsname := p.Name()
|
|
||||||
if nsname.Ptr() != nil {
|
|
||||||
ret = nsname.String()
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) {
|
func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) {
|
||||||
peripheral := Peripheral{
|
ble := cdLookup[c.Ptr()]
|
||||||
Name: peripheralName(p),
|
peripheral := newPeripheral(p)
|
||||||
RSSI: (int)(rssi.IntValue()),
|
peripheral.RSSI = (int)(rssi.IntValue())
|
||||||
identifier: p.Identifier(),
|
|
||||||
p: p,
|
|
||||||
}
|
|
||||||
if peripheral.Name == "" {
|
if peripheral.Name == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ok := ble.peripherals.Add(peripheral); ok {
|
if ok := ble.peripherals.Add(peripheral); ok {
|
||||||
|
pdLookup[p.Ptr()] = ble
|
||||||
ble.events <- DiscoverEvent{Peripheral: peripheral}
|
ble.events <- DiscoverEvent{Peripheral: peripheral}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
|
func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
|
||||||
fmt.Printf("Did connect peripheral\n")
|
fmt.Printf("Did connect peripheral\n")
|
||||||
|
b := cdLookup[c.Ptr()]
|
||||||
|
|
||||||
// set ourselves up as a peripheral delegate
|
// set ourselves up as a peripheral delegate
|
||||||
|
p.SetDelegate(b.cd)
|
||||||
|
|
||||||
p.SetDelegate(cd)
|
uuidstring := p.Identifier().UUIDString().String()
|
||||||
|
peripheral := newPeripheral(p)
|
||||||
id := p.Identifier()
|
|
||||||
peripheral := Peripheral{p: p, identifier: id}
|
|
||||||
found := false
|
found := false
|
||||||
|
|
||||||
ble.peripherals.Lock()
|
b.peripherals.Lock()
|
||||||
for _, item := range ble.peripherals.items {
|
for _, item := range b.peripherals.items {
|
||||||
if item.p.identifier == id {
|
if item.p.Identifier == uuidstring {
|
||||||
peripheral = item.p
|
peripheral = item.p
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ble.peripherals.Unlock()
|
b.peripherals.Unlock()
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
peripheral.Name = peripheralName(p)
|
peripheral.Name = peripheralName(p)
|
||||||
ble.peripherals.Add(peripheral)
|
if ok := b.peripherals.Add(peripheral); ok {
|
||||||
|
pdLookup[p.Ptr()] = b
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ble.events <- ConnectEvent{peripheral}
|
b.events <- ConnectEvent{peripheral}
|
||||||
fmt.Printf("Go: connectPeripheral returning\n")
|
fmt.Printf("Go: connectPeripheral returning\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,6 +315,8 @@ func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
||||||
|
//ble := pdLookup[p]
|
||||||
|
ble := gble
|
||||||
if chr.UUID().IsEqualTo(hrv_uuid) {
|
if chr.UUID().IsEqualTo(hrv_uuid) {
|
||||||
v := chr.Value()
|
v := chr.Value()
|
||||||
ble.Lock()
|
ble.Lock()
|
||||||
|
@ -310,20 +330,18 @@ var (
|
||||||
hrm_uuid *ns.CBUUID
|
hrm_uuid *ns.CBUUID
|
||||||
hrv_uuid *ns.CBUUID
|
hrv_uuid *ns.CBUUID
|
||||||
info_uuid *ns.CBUUID
|
info_uuid *ns.CBUUID
|
||||||
cd *ns.CBDelegate
|
|
||||||
cm *ns.CBCentralManager
|
gble *BLE
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewBLE() *BLE {
|
func NewBLE() *BLE {
|
||||||
if ble != nil {
|
|
||||||
return ble
|
|
||||||
}
|
|
||||||
ps := Peripherals{items: make([]PeripheralListItem,0)}
|
ps := Peripherals{items: make([]PeripheralListItem,0)}
|
||||||
ble = &BLE{events: make(chan interface{}), peripherals: ps}
|
ble := &BLE{events: make(chan interface{}), peripherals: ps}
|
||||||
|
gble = ble
|
||||||
|
|
||||||
queue := ns.DispatchQueueCreate(ns.CharWithGoString("go_hrm_queue"), nil)
|
queue := ns.DispatchQueueCreate(ns.CharWithGoString("go_hrm_queue"), nil)
|
||||||
|
|
||||||
cd = ns.CBDelegateAlloc()
|
cd := ns.CBDelegateAlloc()
|
||||||
|
|
||||||
cd.CentralManagerDidUpdateStateCallback(updateState)
|
cd.CentralManagerDidUpdateStateCallback(updateState)
|
||||||
cd.CentralManagerDidDiscoverPeripheralCallback(discoverPeripheral)
|
cd.CentralManagerDidDiscoverPeripheralCallback(discoverPeripheral)
|
||||||
|
@ -336,8 +354,17 @@ func NewBLE() *BLE {
|
||||||
hrv_uuid = ns.CBUUIDWithGoString("2A37")
|
hrv_uuid = ns.CBUUIDWithGoString("2A37")
|
||||||
info_uuid = ns.CBUUIDWithGoString("180A")
|
info_uuid = ns.CBUUIDWithGoString("180A")
|
||||||
|
|
||||||
|
ble.cd = cd
|
||||||
|
if cdLookup == nil {
|
||||||
|
cdLookup = make(map[unsafe.Pointer]*BLE,0)
|
||||||
|
}
|
||||||
|
if pdLookup == nil {
|
||||||
|
pdLookup = make(map[unsafe.Pointer]*BLE,0)
|
||||||
|
}
|
||||||
|
|
||||||
// We defined our own queue because this won't work on the main queue.
|
// We defined our own queue because this won't work on the main queue.
|
||||||
cm = ns.CBCentralManagerAlloc().InitWithDelegateQueue(cd, queue)
|
ble.cm = ns.CBCentralManagerAlloc().InitWithDelegateQueue(cd, queue)
|
||||||
|
cdLookup[ble.cm.Ptr()] = ble
|
||||||
|
|
||||||
// For debugging purposes, run GC every second to make sure things are
|
// For debugging purposes, run GC every second to make sure things are
|
||||||
// not over-released.
|
// not over-released.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user