7

我正在尝试编写一个简单的应用程序:
1. 扫描可用的 BTLE 设备,以及
2. 将它们放在下拉菜单中供用户查看。

到目前为止,我已经导入了 IOBluetooth 框架,并且我有一个 IBOutlet 到一个 NSPopUpButton(我想在其中显示结果)和两个 IBAction 用于调用 startScan 和 stopScan 的按钮。

我已经有一段时间了,我需要寻求帮助。我看过这个精彩论坛上的其他帖子,但我对 Objective-C 编程比较陌生,非常感谢您的帮助。

这是我的界面:

#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

这是我的实现:

@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's 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's state is updated to: %@", central);
}

- (void)retrievePeripherals:(NSArray *)peripheralUUIDs{
}

@end

就像我说的,我会非常感谢你的帮助。我喜欢编程,但我对此感到沮丧,而且我相信你们中的一个人会看一看这个并确切地知道发生了什么。

谢谢,大卫

4

2 回答 2

10

好的快速概述您需要做什么才能开始:

1.) 在你可以扫描任何东西之前,你需要分配你的 CentralManager,采用它的委托,并等待获得委托回调:

-分配您在标题中声明的中心

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

- 然后等待委托回调

- (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.) 如果您想使用 IBAction 控制扫描,您还需要每次检查状态。

- (IBAction)startScan:(id)sender
{
    if(central.state == CBCentralManagerStatePoweredOn)
    {
        //nil scans for all peripherals. Change to an array of service UUID's 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.) 现在,由于您已经设置了委托和设备扫描,只需等待 didDiscoverPeripheral 回调:

- (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.)将您发现的存储CBPeripherals在一个数组中或仅存储外围名称(取决于您的用例)。将其输入到表的数据中,并在每个新的外围设备发现时调用 reloadData。如果您想跟踪当前附近有哪些,您可以继续并允许重复,您可以根据找到的时间/广告 rssi 删除/添加。

注意:理想情况下,Central 将设置在 Singleton 类中,在该类中,您可以在视图控制器中采用它的委托方法。(但你可以用这种方式弄湿你的脚)。

希望能帮助到你!

于 2013-09-09T19:30:05.980 回答
1

您绝对应该查看来自苹果的 BTLE 示例应用程序:https ://developer.apple.com/library/mac/samplecode/HeartRateMonitor/Introduction/Intro.html这是一个 OSX 应用程序,它实现了您想要尝试的内容。在 Mac 上启动应用程序并使用 iPhone/iPad/iPod 上的LightBlueBLE Utility应用程序来模拟心率传感器。

旁注:WiFi 和 BLE 会干扰 Mac。在测试时使用以太网连接以确保此问题不会妨碍您的测试。William Henderson http://lists.apple.com/archives/bluetooth-dev/2013/Aug/msg00023.html还提供了一个更好的软件解决方案。

现在几个人已经验证了解决方法,这里是:

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

然后你需要重新启动。我已经尝试过,但到目前为止未能找到一种无需重新启动即可使其生效的方法。

于 2013-09-09T21:45:24.950 回答