didReadRSSI called on iOS but not on OS X

Viewed 458

I am trying to write an OS X client that can get frequent updates on the RSSI value for bluetooth peripherals.

My client app is finding my iPhone device on which I am running a test app that is advertising bluetooth services. The client app has a timer that causes a peripheral.readRSSI() to be executed every 3 seconds.

I am having no success getting didReadRSSI to be called when running on OS X, but when I run the exact same Swift code on iOS it works fine.

On iOS 9.3 - didReadRSSI gets called as expected with valid RSSI values.

On OS X 10.11.4 - didReadRSSI is never called.

I am running the following exact same Swift code on iOS and OS X:

import Foundation
import CoreBluetooth

class SampleClient:NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {

var manager: CBCentralManager!
var peripheral: CBPeripheral!
var characteristic: CBCharacteristic!
var readRSSITimer: NSTimer!

override init() {
    super.init()
    self.manager = CBCentralManager(delegate: self, queue: nil)
}

func centralManagerDidUpdateState(central: CBCentralManager) {
    if self.manager.state == .PoweredOn {
        self.manager.scanForPeripheralsWithServices(nil, options: nil)
    }
}

func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
    if let name = peripheral.name {
        print(name)
        self.peripheral = peripheral
        self.manager.connectPeripheral(self.peripheral, options:
            [CBConnectPeripheralOptionNotifyOnDisconnectionKey : true])
    }
}

func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {
    peripheral.readRSSI()
    self.startReadRSSI()
    peripheral.delegate = self
    peripheral.discoverServices(nil)
}

func centralManager(central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) {
    self.stopReadRSSI()
    if self.peripheral != nil {
        self.peripheral.delegate = nil
        self.peripheral = nil
    }
}

func centralManager(central: CBCentralManager, didFailToConnectPeripheral aPeripheral: CBPeripheral, error: NSError?) {
    if self.peripheral != nil {
        self.peripheral.delegate = nil
        self.peripheral = nil
    }
}

func disconnect() {
    if self.characteristic != nil {
        self.peripheral.setNotifyValue(false, forCharacteristic: self.characteristic)
    }
    if self.peripheral != nil {
        self.manager.cancelPeripheralConnection(self.peripheral)
    }
}

func stopScan() {
    self.manager.stopScan()
}

func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
    for service: CBService in peripheral.services! {
        peripheral.discoverCharacteristics(nil, forService: service)
    }
}

func peripheral(peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: NSError?) {
    print("RSSI = \(RSSI)")
}

func readRSSI() {
    if (self.peripheral != nil) {
        self.peripheral.delegate = self
        print("RSSI Request - \(peripheral.name!)")
        self.peripheral.readRSSI()
    } else {
        print("peripheral = nil")
    }
}

func startReadRSSI() {
    if self.readRSSITimer == nil {
        self.readRSSITimer = NSTimer.scheduledTimerWithTimeInterval(3.0, target: self, selector: #selector(SampleClient.readRSSI), userInfo: nil, repeats: true)
    }
}

func stopReadRSSI() {
    if (self.readRSSITimer != nil) {
        self.readRSSITimer.invalidate()
        self.readRSSITimer = nil
    }
}

}

The output when run on iOS is:

iPhone
RSSI = -38
RSSI Request - iPhone
RSSI = -44
RSSI Request - iPhone
RSSI = -45

The output when run on OS X is:

My iPhone 6
RSSI Request - My iPhone 6
RSSI Request - My iPhone 6

Note that the peripheral names returned are different on the two platforms. I do not know if that is significant.

How do I get didReadRSSI to be called on OS X?

1 Answers
Related