Add ble.go to factor out platform-independent code.
This commit is contained in:
parent
5955e369e4
commit
2d4f106dd7
246
ble.go
Normal file
246
ble.go
Normal file
|
@ -0,0 +1,246 @@
|
||||||
|
package ble
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.wow.st/gmp/ble/gatt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PeripheralListItem struct {
|
||||||
|
p Peripheral
|
||||||
|
seen time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type Peripherals struct {
|
||||||
|
items []PeripheralListItem
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnectionListItem struct {
|
||||||
|
p Peripheral
|
||||||
|
state chan string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Connections struct {
|
||||||
|
items []ConnectionListItem
|
||||||
|
close chan struct{}
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connections) UpdateState(p Peripheral, s string) {
|
||||||
|
var ch chan string
|
||||||
|
c.Lock()
|
||||||
|
for _, item := range c.items {
|
||||||
|
if p.Identifier == item.p.Identifier {
|
||||||
|
ch = item.state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.Unlock()
|
||||||
|
ch <- s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *Peripherals) Add(x Peripheral) bool {
|
||||||
|
ps.Lock()
|
||||||
|
defer ps.Unlock()
|
||||||
|
found := false
|
||||||
|
for n, item := range ps.items {
|
||||||
|
if item.p.Identifier == x.Identifier {
|
||||||
|
item.p = x
|
||||||
|
item.seen = time.Now()
|
||||||
|
ps.items[n] = item
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
//take ownership of this object
|
||||||
|
x.Retain()
|
||||||
|
item := PeripheralListItem{p: x, seen: time.Now()}
|
||||||
|
ps.items = append(ps.items, item)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *Connections) Add(x ConnectionListItem) bool {
|
||||||
|
cs.Lock()
|
||||||
|
defer cs.Unlock()
|
||||||
|
found := false
|
||||||
|
for _, item := range cs.items {
|
||||||
|
if item.p.Identifier == x.p.Identifier {
|
||||||
|
// are we allowed to have multiple connections to the same peripheral?
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
cs.items = append(cs.items, x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateStateEvent struct {
|
||||||
|
State string
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiscoverPeripheralEvent struct {
|
||||||
|
Peripheral Peripheral
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: create a Service type that is platform dependent to make the
|
||||||
|
//event platform independent
|
||||||
|
type DiscoverServiceEvent struct {
|
||||||
|
Peripheral Peripheral
|
||||||
|
Gatt gatt.Service
|
||||||
|
Service Service
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: create a Characteristic type that is platform dependent to make the
|
||||||
|
//event platform independent
|
||||||
|
type DiscoverCharacteristicEvent struct {
|
||||||
|
Peripheral Peripheral
|
||||||
|
Gatt gatt.Characteristic
|
||||||
|
Service Service
|
||||||
|
Characteristic Characteristic
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: create a Characteristic type that is platform dependent to make the
|
||||||
|
//event platform independent
|
||||||
|
type UpdateValueEvent struct {
|
||||||
|
Peripheral Peripheral
|
||||||
|
Characteristic Characteristic
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnectEvent struct {
|
||||||
|
Peripheral Peripheral
|
||||||
|
}
|
||||||
|
type ConnectTimeoutEvent struct {
|
||||||
|
Peripheral Peripheral
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdageValueEvent struct {
|
||||||
|
Peripheral Peripheral
|
||||||
|
Characteristic gatt.Characteristic
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BLE) Events() chan interface{} {
|
||||||
|
return b.events
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BLE) State() string {
|
||||||
|
b.Lock()
|
||||||
|
defer b.Unlock()
|
||||||
|
return b.stringState()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BLE) Scan() {
|
||||||
|
b.Lock()
|
||||||
|
defer b.Unlock()
|
||||||
|
if b.readyToScan() {
|
||||||
|
b.peripherals.Lock()
|
||||||
|
b.peripherals.items = b.peripherals.items[:0]
|
||||||
|
b.peripherals.Unlock()
|
||||||
|
fmt.Printf("Go: Scanning\n")
|
||||||
|
b.scan()
|
||||||
|
} else {
|
||||||
|
b.wantScan = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BLE) StopScan() {
|
||||||
|
b.Lock()
|
||||||
|
if !b.ready {
|
||||||
|
b.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.Unlock()
|
||||||
|
fmt.Printf("Go: stopping scan\n")
|
||||||
|
b.stopScan()
|
||||||
|
}
|
||||||
|
|
||||||
|
func connectTracker(b *BLE, x ConnectionListItem) bool {
|
||||||
|
fmt.Printf("connectTracker(): %s\n", x.p.Name)
|
||||||
|
b.connections.Lock()
|
||||||
|
for _, item := range b.connections.items {
|
||||||
|
if item.p.Identifier == x.p.Identifier {
|
||||||
|
fmt.Printf("connectTracker(): already connecting to %s\n", x.p.Name)
|
||||||
|
b.connections.Unlock()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.connections.items = append(b.connections.items, x)
|
||||||
|
b.connections.Unlock()
|
||||||
|
b.connectPeripheral(x.p)
|
||||||
|
|
||||||
|
cancel := func() {
|
||||||
|
b.cancelConnection(x.p)
|
||||||
|
b.connections.Lock()
|
||||||
|
for n, item := range b.connections.items {
|
||||||
|
if item.p.Identifier == x.p.Identifier {
|
||||||
|
b.connections.items = append(b.connections.items[:n], b.connections.items[n+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.connections.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
tick := time.NewTicker(time.Second * 5)
|
||||||
|
select {
|
||||||
|
case <-b.connections.close:
|
||||||
|
fmt.Printf("connectTracker(): Closing connection to %s\n", x.p.Name)
|
||||||
|
b.cancelConnection(x.p)
|
||||||
|
case <-tick.C:
|
||||||
|
fmt.Printf("connectTracker(): Connection to %s timed out\n", x.p.Name)
|
||||||
|
cancel()
|
||||||
|
b.events <- ConnectTimeoutEvent{x.p}
|
||||||
|
case state := <-x.state:
|
||||||
|
if state == "cancel" {
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
fmt.Printf("connectTracker(): state %s\n", state)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BLE) Connect(p Peripheral) bool {
|
||||||
|
b.Lock()
|
||||||
|
if !b.ready {
|
||||||
|
b.Unlock()
|
||||||
|
fmt.Printf("--BLE not ready\n")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
b.Unlock()
|
||||||
|
if p.p == nil {
|
||||||
|
var ok bool
|
||||||
|
p, ok = b.knownPeripheral(p)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item := ConnectionListItem{p, make(chan string)}
|
||||||
|
fmt.Printf("BLE.Connect() calling connectTracker\n")
|
||||||
|
return connectTracker(b, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Disconnect(p Peripheral) {
|
||||||
|
b := peripheralLookup(p)
|
||||||
|
found := false
|
||||||
|
b.connections.Lock()
|
||||||
|
for i, item := range b.connections.items {
|
||||||
|
if item.p.Identifier == p.Identifier {
|
||||||
|
found = true
|
||||||
|
b.connections.items = append(b.connections.items[:i], b.connections.items[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.connections.Unlock()
|
||||||
|
if !found {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.cancelConnection(p)
|
||||||
|
}
|
||||||
|
|
319
ble_darwin.go
319
ble_darwin.go
|
@ -31,6 +31,9 @@ var cdLookup map[unsafe.Pointer]*BLE
|
||||||
var pdLookup map[unsafe.Pointer]*BLE
|
var pdLookup map[unsafe.Pointer]*BLE
|
||||||
var pcache map[unsafe.Pointer]*Peripheral
|
var pcache map[unsafe.Pointer]*Peripheral
|
||||||
|
|
||||||
|
func peripheralLookup(p Peripheral) *BLE {
|
||||||
|
return pdLookup[p.p.Ptr()]
|
||||||
|
}
|
||||||
|
|
||||||
type State string
|
type State string
|
||||||
|
|
||||||
|
@ -42,6 +45,24 @@ type Peripheral struct {
|
||||||
p *ns.CBPeripheral
|
p *ns.CBPeripheral
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Service *ns.CBService
|
||||||
|
type Characteristic *ns.CBCharacteristic
|
||||||
|
|
||||||
|
//Init needs to be called before the BLE library can be used. No setup needed
|
||||||
|
//on Darwin.
|
||||||
|
func Init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Peripheral) Retain() {
|
||||||
|
//NOTE: ns.ObjectAtIndex() calls SetFinalizer for us, which will be a problem
|
||||||
|
//later when we call GC(), so we always first clear the finalizer before
|
||||||
|
//setting a new one.
|
||||||
|
runtime.SetFinalizer(x.p, nil)
|
||||||
|
x.p.Retain()
|
||||||
|
x.p.GC()
|
||||||
|
}
|
||||||
|
|
||||||
func peripheralName(p *ns.CBPeripheral) string {
|
func peripheralName(p *ns.CBPeripheral) string {
|
||||||
var ret string
|
var ret string
|
||||||
nsname := p.Name()
|
nsname := p.Name()
|
||||||
|
@ -68,125 +89,8 @@ func newPeripheral(x *ns.CBPeripheral) Peripheral {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
type PeripheralListItem struct {
|
func (b *BLE) stringState() string {
|
||||||
p Peripheral
|
x := b.state
|
||||||
seen time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type Peripherals struct {
|
|
||||||
items []PeripheralListItem
|
|
||||||
sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConnectionListItem struct {
|
|
||||||
p Peripheral
|
|
||||||
state chan string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Connections struct {
|
|
||||||
items []ConnectionListItem
|
|
||||||
close chan struct{}
|
|
||||||
sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Connections) UpdateState(p Peripheral, s string) {
|
|
||||||
var ch chan string
|
|
||||||
c.Lock()
|
|
||||||
for _, item := range c.items {
|
|
||||||
if p.Identifier == item.p.Identifier {
|
|
||||||
ch = item.state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.Unlock()
|
|
||||||
ch <- s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps *Peripherals) Add(x Peripheral) bool {
|
|
||||||
ps.Lock()
|
|
||||||
defer ps.Unlock()
|
|
||||||
found := false
|
|
||||||
for n, item := range ps.items {
|
|
||||||
if item.p.Identifier == x.Identifier {
|
|
||||||
item.p = x
|
|
||||||
item.seen = time.Now()
|
|
||||||
ps.items[n] = item
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if found {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
//take ownership of this Objective-C object
|
|
||||||
x.p.Retain()
|
|
||||||
runtime.SetFinalizer(x.p, nil)
|
|
||||||
x.p.GC()
|
|
||||||
item := PeripheralListItem{p: x, seen: time.Now()}
|
|
||||||
ps.items = append(ps.items, item)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cs *Connections) Add(x ConnectionListItem) bool {
|
|
||||||
cs.Lock()
|
|
||||||
defer cs.Unlock()
|
|
||||||
found := false
|
|
||||||
for _, item := range cs.items {
|
|
||||||
if item.p.Identifier == x.p.Identifier {
|
|
||||||
// are we allowed to have multiple connections to the same peripheral?
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if found {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
cs.items = append(cs.items, x)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateStateEvent struct {
|
|
||||||
State string
|
|
||||||
}
|
|
||||||
|
|
||||||
type DiscoverPeripheralEvent struct {
|
|
||||||
Peripheral Peripheral
|
|
||||||
}
|
|
||||||
|
|
||||||
type DiscoverServiceEvent struct {
|
|
||||||
Peripheral Peripheral
|
|
||||||
Gatt gatt.Service
|
|
||||||
Service *ns.CBService
|
|
||||||
}
|
|
||||||
|
|
||||||
type DiscoverCharacteristicEvent struct {
|
|
||||||
Peripheral Peripheral
|
|
||||||
Gatt gatt.Characteristic
|
|
||||||
Service *ns.CBService
|
|
||||||
Characteristic *ns.CBCharacteristic
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateValueEvent struct {
|
|
||||||
Peripheral Peripheral
|
|
||||||
Characteristic *ns.CBCharacteristic
|
|
||||||
Data []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConnectEvent struct {
|
|
||||||
Peripheral Peripheral
|
|
||||||
}
|
|
||||||
type ConnectTimeoutEvent struct {
|
|
||||||
Peripheral Peripheral
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdageValueEvent struct {
|
|
||||||
Peripheral Peripheral
|
|
||||||
Characteristic gatt.Characteristic
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BLE) Events() chan interface{} {
|
|
||||||
return b.events
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringState(x ns.CBManagerState) string {
|
|
||||||
switch x {
|
switch x {
|
||||||
case (ns.CBManagerState)(ns.CBManagerStateResetting):
|
case (ns.CBManagerState)(ns.CBManagerStateResetting):
|
||||||
return "resetting"
|
return "resetting"
|
||||||
|
@ -205,10 +109,16 @@ func stringState(x ns.CBManagerState) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BLE) State() string {
|
func (b *BLE) readyToScan() bool {
|
||||||
b.Lock()
|
return b.state == (ns.CBManagerState)(ns.CBManagerStatePoweredOn)
|
||||||
defer b.Unlock()
|
}
|
||||||
return stringState(b.state)
|
|
||||||
|
func (b *BLE) scan() {
|
||||||
|
b.cm.ScanForPeripheralsWithServices(nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BLE) stopScan() {
|
||||||
|
b.cm.StopScan()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BLE) setState(x ns.CBManagerState) {
|
func (b *BLE) setState(x ns.CBManagerState) {
|
||||||
|
@ -217,38 +127,18 @@ func (b *BLE) setState(x ns.CBManagerState) {
|
||||||
b.state = x
|
b.state = x
|
||||||
if b.ready && b.wantScan {
|
if b.ready && b.wantScan {
|
||||||
fmt.Printf("Go: Scanning\n")
|
fmt.Printf("Go: Scanning\n")
|
||||||
b.cm.ScanForPeripheralsWithServices(nil, nil)
|
b.scan()
|
||||||
b.wantScan = false
|
b.wantScan = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BLE) Scan() {
|
func (b *BLE) connectPeripheral(x Peripheral) {
|
||||||
b.Lock()
|
fmt.Printf("BLE.Connect(): calling cm.ConnectPeripheral(%p)\n", x.p.Ptr())
|
||||||
defer b.Unlock()
|
b.cm.ConnectPeripheral(x.p, nil)
|
||||||
if b.state != (ns.CBManagerState)(ns.CBManagerStatePoweredOn) {
|
|
||||||
b.wantScan = true
|
|
||||||
} else {
|
|
||||||
b.peripherals.Lock()
|
|
||||||
b.peripherals.items = b.peripherals.items[:0]
|
|
||||||
b.peripherals.Unlock()
|
|
||||||
fmt.Printf("Go: Scanning\n")
|
|
||||||
b.cm.ScanForPeripheralsWithServices(nil, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BLE) StopScan() {
|
|
||||||
b.Lock()
|
|
||||||
if !b.ready {
|
|
||||||
b.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b.Unlock()
|
|
||||||
fmt.Printf("Go: stopping scan\n")
|
|
||||||
b.cm.StopScan()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CancelConnection(p Peripheral) {
|
func CancelConnection(p Peripheral) {
|
||||||
b := pdLookup[p.p.Ptr()]
|
b := peripheralLookup(p)
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -266,99 +156,24 @@ func CancelConnection(p Peripheral) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectTracker(b *BLE, x ConnectionListItem) bool {
|
func (b *BLE) cancelConnection(p Peripheral) {
|
||||||
fmt.Printf("connectTracker(): %s\n", x.p.Name)
|
b.cm.CancelPeripheralConnection(p.p)
|
||||||
b.connections.Lock()
|
|
||||||
for _, item := range b.connections.items {
|
|
||||||
if item.p.Identifier == x.p.Identifier {
|
|
||||||
fmt.Printf("connectTracker(): already connecting to %s\n", x.p.Name)
|
|
||||||
b.connections.Unlock()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.connections.items = append(b.connections.items, x)
|
|
||||||
b.connections.Unlock()
|
|
||||||
fmt.Printf("BLE.Connect(): calling cm.ConnectPeripheral(%p)\n", x.p.p.Ptr())
|
|
||||||
b.cm.ConnectPeripheral(x.p.p, nil)
|
|
||||||
|
|
||||||
cancel := func() {
|
|
||||||
b.cm.CancelPeripheralConnection(x.p.p)
|
|
||||||
b.connections.Lock()
|
|
||||||
for n, item := range b.connections.items {
|
|
||||||
if item.p.Identifier == x.p.Identifier {
|
|
||||||
b.connections.items = append(b.connections.items[:n], b.connections.items[n+1:]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.connections.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
func (b *BLE) knownPeripheral(p Peripheral) (Peripheral, bool) {
|
||||||
tick := time.NewTicker(time.Second * 5)
|
|
||||||
select {
|
|
||||||
case <-b.connections.close:
|
|
||||||
fmt.Printf("connectTracker(): Closing connection to %s\n", x.p.Name)
|
|
||||||
b.cm.CancelPeripheralConnection(x.p.p)
|
|
||||||
case <-tick.C:
|
|
||||||
fmt.Printf("connectTracker(): Connection to %s timed out\n", x.p.Name)
|
|
||||||
cancel()
|
|
||||||
b.events <- ConnectTimeoutEvent{x.p}
|
|
||||||
case state := <-x.state:
|
|
||||||
if state == "cancel" {
|
|
||||||
cancel()
|
|
||||||
}
|
|
||||||
fmt.Printf("connectTracker(): state %s\n", state)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BLE) Connect(p Peripheral) bool {
|
|
||||||
b.Lock()
|
|
||||||
if !b.ready {
|
|
||||||
b.Unlock()
|
|
||||||
fmt.Printf("--BLE not ready\n")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
b.Unlock()
|
|
||||||
if p.p == nil {
|
|
||||||
fmt.Printf("RetrievePeripheralsWithIdentifiers\n")
|
fmt.Printf("RetrievePeripheralsWithIdentifiers\n")
|
||||||
ps := b.cm.RetrievePeripheralsWithIdentifiers(ns.NSArrayWithObjects(ns.NSUUIDAlloc().InitWithUUIDString(ns.NSStringWithGoString(p.Identifier))))
|
ps := b.cm.RetrievePeripheralsWithIdentifiers(ns.NSArrayWithObjects(ns.NSUUIDAlloc().InitWithUUIDString(ns.NSStringWithGoString(p.Identifier))))
|
||||||
if x := (int)(ps.Count()); x > 0 {
|
if x := (int)(ps.Count()); x > 0 {
|
||||||
fmt.Printf("--found %d\n", x)
|
fmt.Printf("--found %d\n", x)
|
||||||
cbp := ps.ObjectAtIndex(0).CBPeripheral()
|
cbp := ps.ObjectAtIndex(0).CBPeripheral()
|
||||||
//NOTE: ns.ObjectAtIndex() calls SetFinalizer for us, which will be a problem
|
return newPeripheral(cbp), true
|
||||||
//later when we call GC(), so we first clear the finalizer here.
|
|
||||||
runtime.SetFinalizer(cbp, nil)
|
|
||||||
p = newPeripheral(cbp)
|
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("--none found\n")
|
fmt.Printf("--none found\n")
|
||||||
return false
|
return Peripheral{}, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item := ConnectionListItem{p, make(chan string)}
|
|
||||||
fmt.Printf("BLE.Connect() calling connectTracker\n")
|
|
||||||
return connectTracker(b, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Disconnect(p Peripheral) {
|
func didUpdateState(c *ns.CBCentralManager) {
|
||||||
b := pdLookup[p.p.Ptr()]
|
|
||||||
found := false
|
|
||||||
b.connections.Lock()
|
|
||||||
for i, item := range b.connections.items {
|
|
||||||
if item.p.Identifier == p.Identifier {
|
|
||||||
found = true
|
|
||||||
b.connections.items = append(b.connections.items[:i], b.connections.items[i+1:]...)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.connections.Unlock()
|
|
||||||
if !found {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b.cm.CancelPeripheralConnection(p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateState(c *ns.CBCentralManager) {
|
|
||||||
b := cdLookup[c.Ptr()]
|
b := cdLookup[c.Ptr()]
|
||||||
st := c.CBManager.State()
|
st := c.CBManager.State()
|
||||||
if st == (ns.CBManagerState)(ns.CBManagerStatePoweredOn) {
|
if st == (ns.CBManagerState)(ns.CBManagerStatePoweredOn) {
|
||||||
|
@ -378,17 +193,17 @@ func updateState(c *ns.CBCentralManager) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.setState(st)
|
b.setState(st)
|
||||||
b.events <- UpdateStateEvent{State: stringState(st)}
|
b.events <- UpdateStateEvent{State: b.stringState()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) {
|
func didDiscoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) {
|
||||||
b := cdLookup[c.Ptr()]
|
b := cdLookup[c.Ptr()]
|
||||||
peripheral := newPeripheral(p)
|
peripheral := newPeripheral(p)
|
||||||
peripheral.RSSI = (int)(rssi.IntValue())
|
peripheral.RSSI = (int)(rssi.IntValue())
|
||||||
_discoverPeripheral(b, peripheral)
|
_didDiscoverPeripheral(b, peripheral)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _discoverPeripheral(b *BLE, peripheral Peripheral) {
|
func _didDiscoverPeripheral(b *BLE, peripheral Peripheral) {
|
||||||
if peripheral.Name == "" {
|
if peripheral.Name == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -398,7 +213,7 @@ func _discoverPeripheral(b *BLE, peripheral Peripheral) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
|
func didConnectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
|
||||||
fmt.Printf("Did connect peripheral\n")
|
fmt.Printf("Did connect peripheral\n")
|
||||||
b := cdLookup[c.Ptr()]
|
b := cdLookup[c.Ptr()]
|
||||||
|
|
||||||
|
@ -428,7 +243,7 @@ func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
|
||||||
|
|
||||||
b.connections.UpdateState(peripheral, "connected")
|
b.connections.UpdateState(peripheral, "connected")
|
||||||
b.events <- ConnectEvent{peripheral}
|
b.events <- ConnectEvent{peripheral}
|
||||||
fmt.Printf("Go: connectPeripheral returning\n")
|
fmt.Printf("Go: didConnectPeripheral returning\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x Peripheral) DiscoverServices() {
|
func (x Peripheral) DiscoverServices() {
|
||||||
|
@ -440,7 +255,7 @@ func (x Peripheral) DiscoverServices() {
|
||||||
p.DiscoverServices(nil)
|
p.DiscoverServices(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverServices(p *ns.CBPeripheral, e *ns.NSError) {
|
func didDiscoverServices(p *ns.CBPeripheral, e *ns.NSError) {
|
||||||
b := pdLookup[p.Ptr()]
|
b := pdLookup[p.Ptr()]
|
||||||
fmt.Printf("Did discover services\n")
|
fmt.Printf("Did discover services\n")
|
||||||
p.Services().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
p.Services().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
||||||
|
@ -453,7 +268,7 @@ func discoverServices(p *ns.CBPeripheral, e *ns.NSError) {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
fmt.Printf("Go: discoverServices returning\n")
|
fmt.Printf("Go: didDiscoverServices returning\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func hr(d *ns.NSData) int {
|
func hr(d *ns.NSData) int {
|
||||||
|
@ -473,7 +288,7 @@ func (p Peripheral) DiscoverCharacteristics(serv *ns.CBService) {
|
||||||
p.p.DiscoverCharacteristics(nil, serv)
|
p.p.DiscoverCharacteristics(nil, serv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError) {
|
func didDiscoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError) {
|
||||||
b := pdLookup[p.Ptr()]
|
b := pdLookup[p.Ptr()]
|
||||||
fmt.Printf("Did discover characteristics\n")
|
fmt.Printf("Did discover characteristics\n")
|
||||||
s.Characteristics().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
s.Characteristics().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
||||||
|
@ -488,14 +303,14 @@ func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
fmt.Printf("Go: discoverCharacteristics returning\n")
|
fmt.Printf("Go: didDiscoverCharacteristics returning\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Peripheral) SetNotifyValue(c *ns.CBCharacteristic) {
|
func (p Peripheral) SetNotifyValue(c *ns.CBCharacteristic) {
|
||||||
p.p.SetNotifyValue(1, c)
|
p.p.SetNotifyValue(1, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
func didUpdateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
||||||
b := pdLookup[p.Ptr()]
|
b := pdLookup[p.Ptr()]
|
||||||
v := chr.Value()
|
v := chr.Value()
|
||||||
b.events <-UpdateValueEvent{
|
b.events <-UpdateValueEvent{
|
||||||
|
@ -505,33 +320,21 @@ func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
hrm_uuid *ns.CBUUID
|
|
||||||
hrv_uuid *ns.CBUUID
|
|
||||||
info_uuid *ns.CBUUID
|
|
||||||
|
|
||||||
gble *BLE
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewBLE() *BLE {
|
func NewBLE() *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(didUpdateState)
|
||||||
cd.CentralManagerDidDiscoverPeripheralCallback(discoverPeripheral)
|
cd.CentralManagerDidDiscoverPeripheralCallback(didDiscoverPeripheral)
|
||||||
cd.CentralManagerDidConnectPeripheralCallback(connectPeripheral)
|
cd.CentralManagerDidConnectPeripheralCallback(didConnectPeripheral)
|
||||||
cd.PeripheralDidDiscoverServicesCallback(discoverServices)
|
cd.PeripheralDidDiscoverServicesCallback(didDiscoverServices)
|
||||||
cd.PeripheralDidDiscoverCharacteristicsForServiceCallback(discoverCharacteristics)
|
cd.PeripheralDidDiscoverCharacteristicsForServiceCallback(didDiscoverCharacteristics)
|
||||||
cd.PeripheralDidUpdateValueForCharacteristicCallback(updateValue)
|
cd.PeripheralDidUpdateValueForCharacteristicCallback(didUpdateValue)
|
||||||
|
|
||||||
hrm_uuid = ns.CBUUIDWithGoString("180D")
|
|
||||||
hrv_uuid = ns.CBUUIDWithGoString("2A37")
|
|
||||||
info_uuid = ns.CBUUIDWithGoString("180A")
|
|
||||||
|
|
||||||
ble.cd = cd
|
ble.cd = cd
|
||||||
if cdLookup == nil {
|
if cdLookup == nil {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user