Connect to peripherals by UUIDString. Eliminate globals for central

manager and delegate.
This commit is contained in:
Greg 2019-10-24 08:59:25 -04:00
parent 0424b70ef3
commit c91c83de9c
1 changed files with 71 additions and 44 deletions

View File

@ -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.