I would like to discover BLE devices in my area and store their current RSSI value. The discovering works but I'm note sure, if my func didDiscoverPeripheral is really save... I think that I should wait for the didReadRSSI func before I leave the didDiscoverPeripheral. But how can I realize that in an easy way and is my opinion right?
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber)
{
CBperipheral = [peripheral]
peripheral.readRSSI()
}
func peripheral(peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: NSError?)
{
//Store the peripheral specific RSSI, Name and identifier
}
I would suggest something like this -
var peripherals = Set<CBPeripheral>
var peripheralRSSIs = Dictionary<CBPeripheral,NSNumber>()
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber)
{
self.peripherals.insert(peripheral)
self.peripheralRSSIs[peripheral]=RSSI
central.connectPeripheral(peripheral,options:nil) // Connect if you want to be able to retrieve additional RSSI values
}
func centralManager(_ central: CBCentralManager,
didConnectPeripheral peripheral: CBPeripheral)
{
peripheral.delegate=self
peripheral.readRSSI()
}
func peripheral(peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: NSError?)
{
if (error != nil) {
print(error)
} else {
self.peripheralRSSIs[peripheral]=RSSI
}
}
I solved the problem like this:
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber)
{
CBperipheral = [peripheral]
myStrings.append(StringPair("\(peripheral.name!)", "\(peripheral.name!)", "\(RSSI)"))
//Coose the right peripheral and connect!
}
I don't need very up-to-date values for the RSSI, only some guiding values. So I hope this code is conform with IOS 8 and later.
But it would be nice, if you could tell me the handling with the callback to my didReadRSSI for other problems like this.
btw. I have to write this: CBperipheral = [peripheral] to call my didConnectPeripheral after the call of CBmanager.connectPeripheral :)
Related
var peripherals = [CBPeripheral]()
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if let _ = peripheral.name {
if !peripherals.contains(peripheral) {
peripherals.append(peripheral)
table.reloadData()
}
}
}
Using the delegate method above, called after centralManager.scanForPeripherals(withServices: nil), I am showing available peripherals(only those with name).
Since some of the available devices are also mine, I am sure that bluetooth is turned off on them.
So why does this method returns them as available? Are they cached somewhere or?
I'm trying to connect near by bluetooth devices. I'm able to discover but i'm unable to connect them.
this delegate is working but after discovering i'm trying connect with one of the pheripheral
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if let device = (advertisementData as NSDictionary).object(forKey: CBAdvertisementDataLocalNameKey) as? String {
print(device)
if device.contains("BODY") {
self.connectPeripheral = peripheral
self.connectPeripheral.delegate = self
self.manager.connect(connectPeripheral, options: nil)
self.manager.stopScan()
}
}
}
These two delegates methods are not invoking. one of these should be called.
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheral.delegate = self
peripheral.discoverServices(nil)
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
//NSLog("Error %#", error.debugDescription)
print(error.debugDescription)
}
You need to maintain a strong reference to the CBPeripheral instance, because once you tell the Central to stop scanning, it will deallocate all its discovered peripherals.
I have BLE source code that displays several warnings and I am new to
BLE. Please see the code below. I have tried replacing with readRSSI but tells me I can’t compare an Int with Void. How do I get an Int value for readRSSI? Or how should I change the code?
- (void)peripheralDidUpdateRSSI:(CBPeripheral * _Nonnull)peripheral error:(NSError * _Nullable)error
{
if (!isConnected)
return;
if (rssi != peripheral.RSSI.intValue)
{
rssi = peripheral.RSSI.intValue;
[[self delegate] bleDidUpdateRSSI:activePeripheral.RSSI];
}
}
*rssi is a static int.
*isConnected is a boolean.
Edit: The problem is that RSSI is deprecated since iOS 8.0.
There are two ways of obtaining the CBPeripheral's RSSI. The first is when the peripheral is discovered. You will get a call to the CBCentralManagerDelegate method
func centralManager(_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any],
rssi RSSI: NSNumber) {
let rssi = intValue
...
}
If you are running in the foreground then you can supply a value of true to for the key CBCentralManagerScanOptionAllowDuplicatesKey in the scanning options to get repeated calls to didDiscover. This doesn't work in the background.
If you are connected to a peripheral then you can periodically call peripheral.readRSSI(). This will result in a callback to the didReadRSSI CBPeripheralDelegate method:
optional func peripheral(_ peripheral: CBPeripheral,
didReadRSSI RSSI: NSNumber,
error: Error?) {
let rssi = RSSI.intValue
...
}
swift 3
#IBAction func btnGetRSSI(_ sender: UIButton){
self.selectedPeripehral.readRSSI()
}
func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
var rssiInt: Int!
rssiInt = RSSI.intValue
}
I am new to iOS and Swift. I had some code from previous XCode which I updated to what I thought was the new cool way to do things, according to the new naming conventions.
For example I had a function in a CBDelegateManager class:
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
...
}
But then I changed it to
func centralManager(central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
...
}
The 2nd matches the online help for the API. Both compile fine, but the 2nd does not get called.
Am I missing something?
I'm not sure why this code is failing to build and the error message seems quite cryptic.
Code:
var centralManager: CBCentralManager!;
var nrf8001Peripheral: CBPeripheral!;
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// initialize centralManager
self.centralManager = CBCentralManager(delegate: self, queue: nil);
// start scanning for device
self.centralManager.scanForPeripheralsWithServices([UART_SERVICE_UUID], options:nil);
}
func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData advertisementData: [NSObject : AnyObject]!, RSSI RSSI: NSNumber) {
//print out the name of the scanned peripheral
print("Discovered \(peripheral.name)")
//print out the UUID of the scanned peripheral
print("NSUUID string \(peripheral.identifier.UUIDString)")
//stop scanning when found
self.centralManager.stopScan()
//connect when found
self.centralManager.connectPeripheral(peripheral, options:nil);
}
And the error I receive from the XCode compiler is:
"Objective-C method 'centralManager:didDiscoverPeripheral:advertisementData:RSSI:' provided by method 'centralManager(:didDiscoverPeripheral:advertisementData:RSSI:)' conflicts with optional requirement method 'centralManager(:didDiscoverPeripheral:advertisementData:RSSI:)' in protocol 'CBCentralManagerDelegate'"
From looking through the CoreBluetooth documentation it seems as if the method syntax and parameters are correct, and the optionality of the parameters is copied directly from the spec sheet: https://developer.apple.com/library/ios/documentation/CoreBluetooth/Reference/CBCentralManagerDelegate_Protocol/#//apple_ref/occ/intfm/CBCentralManagerDelegate/centralManager:didDiscoverPeripheral:advertisementData:RSSI:
Any help would be appreciated! Thank you
Per the comments:
Using XCode 7 beta
When I change the function declaration to:
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData advertisementData: [NSObject : AnyObject], RSSI RSSI: NSNumber)
I still get the same build error.
My centralManagerDidUpdateState:method is
func centralManagerDidUpdateState(central: CBCentralManager) {
print("centralManagerDidUpdateState:");
switch (central.state) {
case .PoweredOff:
print("CBCentralManagerStatePoweredOff");
case .Resetting:
print("CBCentralManagerStateResetting");
case .PoweredOn:
print("CBCentralManagerStatePoweredOn");
//scan for peripheral devices
self.centralManager.scanForPeripheralsWithServices([UART_SERVICE_UUID], options:nil);
case .Unauthorized:
print("CBCentralManagerStateUnauthorized");
case .Unsupported:
print("CBCentralManagerStateUnsupported");
default:
print("CBCentralManagerStateUnknown");
}
}
Thank you for the suggestions; I ended up finding the answer through the XCode 7 documentation. The XCode 6 syntax for the following functions was as follows:
func centralManagerDidUpdateState(central: CBCentralManager!) {}
func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData advertisementData: [NSObject : AnyObject]!, RSSI RSSI: NSNumber) {}
func centralManager(central: CBCentralManager!, didConnectPeripheral peripheral: CBPeripheral!) {}
func centralManager(central: CBCentralManager!, didDisconnectPeripheral peripheral: CBPeripheral!, error: NSError!) {}
func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: NSError!) {}
func peripheral(peripheral: CBPeripheral!, didDiscoverCharacteristicsForService service: CBService!, error: NSError!) {}
func peripheral(peripheral: CBPeripheral!, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {}
func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {}
However, these functions will conflict with the XCode 7 CoreBluetooth library declarations.
Note the differing uses of optionals as well as data types.
(XCode 6) error:NSError! vs. (XCode 7) error:NSError?
(XCode 6) advertisementData : [NSObject : AnyObject]! vs. (XCode 7) advertisementData [String : AnyObject]
The appropriate function declarations for XCode 7 beta are actually the following:
func centralManagerDidUpdateState(central: CBCentralManager) {}
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {}
func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {}
func centralManager(central: CBCentralManager, didFailToConnectPeripheral peripheral: CBPeripheral, error: NSError?) {}
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {}
func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) {}
func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {}
func peripheral(peripheral: CBPeripheral, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic, error: NSError?) {}
func centralManager(central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) {}
Hope this is helpful to others having the same issues!