Is there a way to discover all Bluetooth devices in an iOS app? I am using CoreBluetooth and I get all iDevices around plus one unknown device. However if I go to General -> Bluetooth -> Devices it lists a couple of devices that are not listed by the example app I am making. I need to find a none Apple device in the list and connect to it. Is this possible? And how come the two lists (the system one and the one in the app) are different?
In case it is important it needs to be used for ODB2 system later on, but for now just listing the none Apple device in the discovered devices will do.
Here is the code I am using to list the devices:
class HRMViewController: UIViewController {
var centralManager: CBCentralManager!
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
}
extension HRMViewController: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unknown:
print("central.state is .unknown")
case .resetting:
print("central.state is .resetting")
case .unsupported:
print("central.state is .unsupported")
case .unauthorized:
print("central.state is .unauthorized")
case .poweredOff:
print("central.state is .poweredOff")
case .poweredOn:
print("central.state is .poweredOn")
centralManager.scanForPeripherals(withServices: nil)
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print(advertisementData)
print(peripheral)
}
}
Related
I'm currently trying to make an app that connects to a bluetooth device and once done prints out the
I'm having the problem once it connects it doesn't print out the services and instead prints out "while delegate is either nil or does not implement peripheral:didDiscoverServices:". But the problem is that I do have didDiscoverServices.
Here is my viewcontroller
import UIKit
import CoreBluetooth
let rowerServiceCBUUID = CBUUID(string: "CE060000-43E5-11E4-916C-0800200C9A66")
class HRMViewController: UIViewController {
#IBOutlet weak var heartRateLabel: UILabel!
#IBOutlet weak var bodySensorLocationLabel: UILabel!
var centralManager: CBCentralManager!
var pmPeripheral: CBPeripheral!
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil)
// Make the digits monospaces to avoid shifting when the numbers change
heartRateLabel.font = UIFont.monospacedDigitSystemFont(ofSize: heartRateLabel.font!.pointSize, weight: .regular)
}
func onHeartRateReceived(_ heartRate: Int) {
heartRateLabel.text = String(heartRate)
print("BPM: \(heartRate)")
}
}
extension HRMViewController: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unknown:
print("central.state is .unknown")
case .resetting:
print("central.state is .resetting")
case .unsupported:
print("central.state is .unsupported")
case .unauthorized:
print("central.state is .unauthorized")
case .poweredOff:
print("central.state is .poweredOff")
case .poweredOn:
print("central.state is .poweredOn")
centralManager.scanForPeripherals(withServices: [rowerServiceCBUUID])
#unknown default: break
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print(peripheral)
pmPeripheral = peripheral
centralManager.stopScan()
centralManager.connect(pmPeripheral!)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Connected!")
pmPeripheral.discoverServices(nil)
}
}
extension HRMViewController: CBPeripheralDelegate {
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
guard let services = peripheral.services else { return }
for service in services {
print(service)
pmPeripheral.delegate = self
}
}
}
Does anyone know what I should do? Thanks.
Although you set your central manager's delegate, you have not set the peripheral's delegate. In centralManager(_,didDiscover,advertisementData), add:
pmPeripheral.delegate = self
That should resolve your warning and the delegate method will be called.
I am using CBCentralManager to scan for nearby BLE devices. Below is sample code:-
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOff:
debugPrint("Central manager state is Powered Off")
case .poweredOn:
debugPrint("Central manager state is Powered On")
loggerUtils.log.debug("Central manager state is Powered On")
centralManager.scanForPeripherals(withServices: nil, options: nil)
case .resetting:
debugPrint("Central manager state is resetting")
case .unauthorized:
debugPrint("Central manager state is unauthorised")
case .unknown:
debugPrint("Central manager state is unknown")
case .unsupported:
debugPrint("Central manager state is unsupported")
default:
debugPrint("Central Manager state is unrecognised....enum raw value is \(central.state.rawValue)")
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("\n****\nPeripheral is \(peripheral.name ?? "No Name")\n*****\nAdvertisement data is \(advertisementData)\n*****\nRSSI is \(RSSI) ")
}
It shows the nearby speakers and other BLE enabled devices. But it is not showing any Android Phone whose bluetooth is powered on from settings option. I can see the android device in device list inSettings->Bluetooth in same iPhone.
I am developing an iOS application for Heart rate monitoring, and want to connect a garmin device to my application using Bluetooth.
But I am not able to list down any Garmin device Using Core bluetooth in Swift using (180D Service UUID).
func startUpCentralManager() {
print("Initializing central manager")
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func discoverDevices() {
print("discovering devices")
let services = [CBUUID(string: HRM_HEART_RATE_SERVICE_UUID),CBUUID(string:HRM_DEVICE_INFO_SERVICE_UUID),CBUUID(string:HRM_DEVICE_BATTERY_LEVEL_SERVICE_UUID),CBUUID(string:CALORIE_SERVICE)]
centralManager.scanForPeripherals(withServices: services, options: nil)
}
//MARK: CBCentralManagerDelegate
func centralManagerDidUpdateState(_ central: CBCentralManager) {
print("checking state")
switch (central.state) {
case .poweredOff:
print("CoreBluetooth BLE hardware is powered off")
case .poweredOn:
print("CoreBluetooth BLE hardware is powered on and ready")
blueToothReady = true;
case .resetting:
print("CoreBluetooth BLE hardware is resetting")
case .unauthorized:
print("CoreBluetooth BLE state is unauthorized")
case .unknown:
print("CoreBluetooth BLE state is unknown");
case .unsupported:
print("CoreBluetooth BLE hardware is unsupported on this platform");
}
if blueToothReady {
discoverDevices()
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
let nameOfDeviceFound = (advertisementData as NSDictionary).object(forKey: CBAdvertisementDataLocalNameKey) as? NSString
print("\(String(describing: nameOfDeviceFound))")
print("Discovered Peripheral name : ", peripheral.name ?? String())
if !Utilities.allPeripheralList.contains(peripheral)
{
Utilities.allPeripheralList.add(peripheral)
}
let deviceObj = DeviceModel()
deviceObj.deviceName = peripheral.name ?? String()
deviceObj.UDID = String(format: "%#",(peripheral.identifier).uuidString)
self.addingPeripheralToGlobalSearchArray(obj: deviceObj)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheral.delegate = self
peripheral.discoverServices(nil)
self.connected = peripheral.state == CBPeripheralState.connected ? "YES" : "NO"
print("Connection Status : %#", self.connected)
if self.connected == "YES"{
Utilities.sharedInstance.goToDashboardTabBarScreen(viewController: self)
}
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
// central.scanForPeripherals(withServices: nil, options: nil)
}
func addingPeripheralToGlobalSearchArray(obj:DeviceModel){
var isFound:Bool = false
for i in 0..<Utilities.allDeviceList.count{
let deviceObj = Utilities.allDeviceList[i] as! DeviceModel
if obj.UDID == deviceObj.UDID{
isFound = true
}
}
if !isFound{
Utilities.allDeviceList.add(obj)
}
}
Above is the code which I am using to list down BLE devices. I am able to find Mio-Fuse devices using same peace of code but not Garmin devices.
You need to use the Garmin Standard SDK. Contact Garmin and register as a developer. You cannot connect directly using BLE you have to connect via the Garmin SDK API.
I'm trying to scan for a specific BLE Device on my app by specifying a CBUUID in the scanForPeripheralsWithServices(), but if I mention it scan is never processed.
Here is my CBCentralManagerDelegate code:
func centralManagerDidUpdateState(central: CBCentralManager) {
switch (central.state) {
case CBCentralManagerState.PoweredOff:
print("BLE powered off")
self.clearDevices()
case CBCentralManagerState.Unauthorized:
// Indicate to user that the iOS device does not support BLE.
print("BLE not supported")
break
case CBCentralManagerState.Unknown:
// Wait for another event
print("BLE unknown event")
break
case CBCentralManagerState.PoweredOn:
print("BLE powered on")
self.startScanning()
break
case CBCentralManagerState.Resetting:
print("BLE reset")
self.clearDevices()
case CBCentralManagerState.Unsupported:
print("BLE unsupported event")
break
}
}
func startScanning() {
print("\(NSDate()) Start scanning...")
if let central = centralManager {
let dictionaryOfOptions = [CBCentralManagerScanOptionAllowDuplicatesKey : true]
let ble = [CBUUID(string: "B737D0FF-AF53-9B83-E5D2-922140A9FFFF")]
central.scanForPeripheralsWithServices(ble, options: nil)
}
}
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
print("Discovered peripheral \(RSSI) dBM name: \(peripheral.name)")
print("UUID: \(peripheral.identifier.UUIDString)")
print("Peripheral \(peripheral.identifier)")
.....send event to server....
sleep(delayPolling)
self.startScanning()
}
If I change the scanForPeripheralsWithServices() without any CBUUID String it works fine:
central.scanForPeripheralsWithServices(nil, options: dictionaryOfOptions)
My main concern if to be able to launch this Thread in background and from Apple documentation, we need to scan for a specific device by specifying the CBUUID to be able to run my task.
Can you tell me where I'm wrong?
I am 99% sure I followed the instructions to setup CoreBluetooth correctly. No matter what I do, when I run this app on my iPad mini, the Bluetooth is saying its on. It's saying it is scanning for devices, but it is absolutely not finding any devices. If I go to the Bluetooth menu on the device I do see other devices being discovered. I initialize the CBCentralManager. I setup centralManagerDidUpdateState. When that is sure the bluetooth is ready it calls centralManager.scanForPeripheralsWithServices. All this is happening correctly. But my delegate function centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI: NSNumber!) never ever gets called. My code is very simple. Maybe I am missing something but I was able to confirm that my Macbook is a BTLE device and my ipad mini is a BTLE device as well. Here is my code.
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBCentralManagerDelegate {
var centralManager:CBCentralManager!
var blueToothReady = false
override func viewDidLoad() {
super.viewDidLoad()
startUpCentralManager()
}
func startUpCentralManager() {
println("Initializing central manager")
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func discoverDevices() {
println("discovering devices")
centralManager.scanForPeripheralsWithServices(nil, options: nil)
}
func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI: NSNumber!) {
println("Discovered \(peripheral.name)")
}
func centralManagerDidUpdateState(central: CBCentralManager!) {
println("checking state")
switch (central.state) {
case .PoweredOff:
println("CoreBluetooth BLE hardware is powered off")
case .PoweredOn:
println("CoreBluetooth BLE hardware is powered on and ready")
blueToothReady = true;
case .Resetting:
println("CoreBluetooth BLE hardware is resetting")
case .Unauthorized:
println("CoreBluetooth BLE state is unauthorized")
case .Unknown:
println("CoreBluetooth BLE state is unknown");
case .Unsupported:
println("CoreBluetooth BLE hardware is unsupported on this platform");
}
if blueToothReady {
discoverDevices()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I had to get my macbook advertising. Once I did that using https://github.com/mttrb/BeaconOSX it worked exactly as I had written it.