How to make a drop-down list of available Bluetooth devices in Objective-C?

I am trying to write a simple application that:
1. Scan available BTLE devices and
2. Puts them in a drop-down menu for viewing by the user.

So far, Ive imported the IOBluetooth infrastructure, and I have one IBOutlet for NSPopUpButton (where I want to display the results) and two IBActions for buttons called startScan and stopScan.

I have been for a while, and I need to ask for help. I look at other posts in this wonderful forum, but I'm relatively new to Objective-C programming, and I would really appreciate your help.

Here is my interface:

#import <Cocoa/Cocoa.h> #import <IOBluetooth/IOBluetooth.h> @interface AppDelegate : NSObject <NSApplicationDelegate, CBCentralManagerDelegate, CBPeripheralDelegate> { CBCentralManager * central; // these properties are for the CBCentralManager CBPeripheral * peripheral; NSMutableDictionary * dictionary; NSNumber * number; } @property (assign) IBOutlet NSWindow *window; @property (weak) IBOutlet NSPopUpButton *deviceList; @property NSMutableArray * list; // this is the array to fill up the deviceList NSPopUpButton - (IBAction)startScan:(id)sender; - (IBAction)stopScan:(id)sender; @end 

Here is my implementation:

 @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application CBCentralManager * central = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil]; NSLog(@"Central Manager state is: %li", central.state); } - (IBAction)startScan:(id)sender { // start scanning button NSLog(@"Started scan. Discovering peripherals."); NSArray * list; } - (IBAction)stopScan:(id)sender { // stop scanning button } - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { // I'm not sure how to make this work } - (void)centralManagerDidUpdateState:(CBCentralManager *)central { NSLog(@"Central manager state is updated to: %@", central); } - (void)retrievePeripherals:(NSArray *)peripheralUUIDs{ } @end 

As I said, I would be very grateful for your help. I LOVE programming , but I'm upset about it, and I'm sure one of you will consider this and know exactly what is going on.

Thanks David

+7
objective-c cocoa bluetooth macos core-bluetooth
source share
2 answers

Ok, a quick overview of what you need to do to get started:

1.) Before you can scan something, you need to select CentralManager, accept its delegate and wait to receive the delegate callback:

- Select the center part indicated in the title

 central = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil]; 

-After waiting for the delegate callback

 - (void)centralManagerDidUpdateState:(CBCentralManager *)central { if(central.state == CBCentralManagerStatePoweredOn) { //okay your good to go and can now scan } else { //Unable to use CentralManager methods so print out the central.state and find out why } } 

2.) If you want to use IBAction to control the scan, you also need to check the status every time.

 - (IBAction)startScan:(id)sender { if(central.state == CBCentralManagerStatePoweredOn) { //nil scans for all peripherals. Change to an array of service UUID if you're looking for specific devices. Change NO to YES if you want to allow duplicates [central scanForPeripheralsWithServices:nil options:[NSDictionary dictionaryWithObjectsAndKeys:@NO, CBCentralManagerScanOptionAllowDuplicatesKey, nil]; } } 

3.) Now, since you already configured the delegate and scan for devices, just wait until the didDiscoverPeripheral callback occurred:

 - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { //you've found a peripheral so add it to your table } 

4.) Save the detected CBPeripherals inside the array or only the names of peripheral devices (depending on your use case). Submit this to your table data and call reloadData for each new peripheral discovery. You can continue and allow duplicates if you want to keep track of which ones are nearby, and you can remove / add depending on the rssi time / advertisement found.

Note. The central device should ideally be configured inside the Singleton class in which you accept its delegation methods inside your view controller. (But you can wet your feet this way).

Hope this helps!

+10
source share

You should definitely look at an example BTLE application from apple: https://developer.apple.com/library/mac/samplecode/HeartRateMonitor/Introduction/Intro.html This is an OSX application that implements exactly what you want to try out. Launch the app on Mac and use LightBlue or BLE Utility on iPhone / iPad / iPod to simulate a heart rate sensor.

Side note: WiFi and BLE may affect the Mac. Use an Ethernet connection during testing to make sure that this problem does not interfere with your testing. An even better software solution is also available from William Henderson http://lists.apple.com/archives/bluetooth-dev/2013/Aug/msg00023.html .

Now that a couple of people have checked the workaround, here it is:

 sudo defaults write /Library/Preferences/com.apple.airport.bt.plist bluetoothCoexMgmt Hybrid 

Then you need to reboot. I tried and still could not find a way for this to take effect without a reboot.

+1
source share

All Articles