From c91c83de9c59d03222c9c33732a710c45cca8953 Mon Sep 17 00:00:00 2001 From: Greg Date: Thu, 24 Oct 2019 08:59:25 -0400 Subject: [PATCH] Connect to peripherals by UUIDString. Eliminate globals for central manager and delegate. --- ble_darwin.go | 115 +++++++++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 44 deletions(-) diff --git a/ble_darwin.go b/ble_darwin.go index ec544e2..154872f 100644 --- a/ble_darwin.go +++ b/ble_darwin.go @@ -8,6 +8,7 @@ import ( "runtime" "sync" "time" + "unsafe" "git.wow.st/gmp/ble/ns" ) @@ -22,22 +23,39 @@ type BLE struct { ready, wantScan bool 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 Peripheral struct { Name string RSSI int + Identifier string - identifier *ns.NSUUID p *ns.CBPeripheral } -func (p Peripheral) Identifier() string { - return p.identifier.UUIDString().String() +func peripheralName(p *ns.CBPeripheral) 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 { @@ -55,7 +73,7 @@ func (ps *Peripherals) Add(x Peripheral) bool { defer ps.Unlock() found := false for n,item := range ps.items { - if item.p.identifier.IsEqual(x.identifier) { + if item.p.Identifier == x.Identifier { item.p = x item.seen = time.Now() ps.items[n] = item @@ -118,7 +136,7 @@ func stringState(x ns.CBManagerState) string { func (b *BLE) State() string { b.Lock() defer b.Unlock() - return stringState(ble.state) + return stringState(b.state) } func (b *BLE) setState(x ns.CBManagerState) { @@ -128,7 +146,7 @@ func (b *BLE) setState(x ns.CBManagerState) { if b.ready && b.wantScan { go func() { fmt.Printf("Go: Scanning\n") - cm.ScanForPeripheralsWithServices(nil, nil) + b.cm.ScanForPeripheralsWithServices(nil, nil) }() } } @@ -141,7 +159,7 @@ func (b *BLE) Scan() { } else { b.Unlock() fmt.Printf("Go: Scanning\n") - cm.ScanForPeripheralsWithServices(nil, nil) + b.cm.ScanForPeripheralsWithServices(nil, nil) } } @@ -153,7 +171,7 @@ func (b *BLE) StopScan() { } b.Unlock() fmt.Printf("Go: stopping scan\n") - cm.StopScan() + b.cm.StopScan() } func (b *BLE) Connect(p Peripheral) { @@ -163,13 +181,22 @@ func (b *BLE) Connect(p Peripheral) { return } 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") } func updateState(c *ns.CBCentralManager) { + ble := cdLookup[c.Ptr()] fmt.Printf("Go: did update state\n") - st := cm.CBManager.State() + st := c.CBManager.State() if st == (ns.CBManagerState)(ns.CBManagerStatePoweredOn) { ble.ready = true } else { @@ -179,57 +206,48 @@ func updateState(c *ns.CBCentralManager) { 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) { - peripheral := Peripheral{ - Name: peripheralName(p), - RSSI: (int)(rssi.IntValue()), - identifier: p.Identifier(), - p: p, - } + ble := cdLookup[c.Ptr()] + peripheral := newPeripheral(p) + peripheral.RSSI = (int)(rssi.IntValue()) if peripheral.Name == "" { return } if ok := ble.peripherals.Add(peripheral); ok { + pdLookup[p.Ptr()] = ble ble.events <- DiscoverEvent{Peripheral: peripheral} } } func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) { fmt.Printf("Did connect peripheral\n") + b := cdLookup[c.Ptr()] // set ourselves up as a peripheral delegate + p.SetDelegate(b.cd) - p.SetDelegate(cd) - - id := p.Identifier() - peripheral := Peripheral{p: p, identifier: id} + uuidstring := p.Identifier().UUIDString().String() + peripheral := newPeripheral(p) found := false - ble.peripherals.Lock() - for _, item := range ble.peripherals.items { - if item.p.identifier == id { + b.peripherals.Lock() + for _, item := range b.peripherals.items { + if item.p.Identifier == uuidstring { peripheral = item.p found = true break } } - ble.peripherals.Unlock() + b.peripherals.Unlock() if !found { 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") } @@ -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) { + //ble := pdLookup[p] + ble := gble if chr.UUID().IsEqualTo(hrv_uuid) { v := chr.Value() ble.Lock() @@ -310,20 +330,18 @@ var ( hrm_uuid *ns.CBUUID hrv_uuid *ns.CBUUID info_uuid *ns.CBUUID - cd *ns.CBDelegate - cm *ns.CBCentralManager + + gble *BLE ) func NewBLE() *BLE { - if ble != nil { - return ble - } 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) - cd = ns.CBDelegateAlloc() + cd := ns.CBDelegateAlloc() cd.CentralManagerDidUpdateStateCallback(updateState) cd.CentralManagerDidDiscoverPeripheralCallback(discoverPeripheral) @@ -336,8 +354,17 @@ func NewBLE() *BLE { hrv_uuid = ns.CBUUIDWithGoString("2A37") 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. - 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 // not over-released.