OBJ-C 操作方法:在同一设备中使用 BLE 连接和 iBeacon 的应用

OBJ-C how-to: App using BLE connection and iBeacon in same device

我有一个用例,我的 objective-c 应用程序在终止后需要立即使用 iBeacon,以便将应用程序从终止状态唤醒,连接到 BLE 并向设备发送命令。我有一个更大更长的 运行ning 如果需要你可以查看我的代码。

问题

到目前为止,问题发生在我 运行 应用程序搜索以前配对的设备 and/or 扫描外围设备,找到我的 BLE 设备并连接时。连接后,用户将 BLE 连接配对,以便他们可以通过 BLE 连接发送加密的特征数据。如果没有配对(在设备的命名约定中也称为 auth/bond),用户根本无法将数据发送到设备。它永远不会到达那里。一旦配对,您就可以发送命令...

当我终止应用程序时,在 applicationWillTerminate 方法中,我 运行 通过此代码...

- (void)applicationWillTerminate:(UIApplication *)application {
    NSLog(@"*** Application Will Terminate.");

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSNumber *mode = [userDefaults objectForKey:@"deviceConnectedMode"];

    if([mode intValue] == CONNECTED_MODE_INDICATOR) {
        [self.bluetoothManager sendCodeToBTDevice:@"magiccommand1"
                                   characteristic:self.bluetoothManager.wipeCharacteristic];

//I have been turning this command on and off in testing to see if I can get it to work better while disconnecting in the device rather than in the app...
//The command magiccommand2 wipes the auth/bond inside of the device           
//        [self.bluetoothManager sendCodeToBTDevice:@"magiccommand2"
//                                   characteristic:self.bluetoothManager.disconnectCharacteristic];

        //Place where I attempt to stop being connected to BT
        [self.bluetoothManager disconnectDevice];
        [self.beaconManager startMonitoring];

        NSLog(@"*** Application terminated from connected mode!");

    } else {
        NSLog(@"*** DriveCare terminated without violation!");
    }
}

我想要完成的事情

magiccommand1magiccommand2 命令只是愚蠢的测试字符串(现在,128 位令牌以后),设备正在通过串行端口侦听。一旦他们收到命令,他们就会尝试擦除设备上的 auth/bond 并与设备中的 BLE 断开连接。

所以我似乎可以让应用程序从终止状态唤醒的唯一方法是使用 iBeacon。所以我不得不在这里做一堆看似肮脏的事情只是为了把这个圆钉放在方孔里。在应用程序的生命周期中,它会连接和配对,当我终止时,我希望它作为连接设备从 BLE 中完全删除。我希望 iBeacon 将唤醒应用程序,连接回 BLE,关闭 iBeacon 监控,然后从终止状态向 BLE 设备发送命令。 on/off 或 connecting/disconnecting 从 iBeacon 到 BLE 并返回很可能导致用户必须重新配对,我不希望这样。

更多问题

当我调用 [self.centralManager cancelPeripheralConnection:self.thePeripheral]; 时,iOS 系统级 BT 管理器似乎几乎立即自动重新连接(因为配对)所以没有时间切断连接和 iBeacon 是又捡起来了。如果我在将断开连接命令发送到我的盒子之前尝试断开与我的 centralManager 实例的连接(如上面注释掉的代码所示),它们显然不会发送任何一个。如果我只使用 CBCentralManager 断开连接方法,则 iBeacon 不足以开始被检测到,因为 iOS 系统仍与设备配对。最后,如果我随后进入我的 iOS 系统 BT 管理器并选择 "Forget this device",iBeacon 将再次被拾取并且我的 didEnterRegion 方法会触发!

iBeacon 和 BLE 之间有很多来回,我只是希望我什至不需要 iBeacon 来唤醒应用程序。我已打开所有 info.plist 后台 BLE 和 iBeacon 服务。如果我根本不连接到 BLE 并且从不配对并连接我的设备,本地应用程序通知会毫无问题地滑入,让我知道 iBeacon didEnterRegiondidExitRegion 方法正在被触发而没有问题.

我做错了什么?

我想出了这个答案!我走在正确的道路上……尝试断开 BT 配对以尝试触发 iBeacon 委托方法并不是一个好主意。它会导致很多奇怪的脏代码,不应该的紧密耦合的东西,更糟糕的是......可怕的意大利面条代码。

相反,我的解决方案是构建一个带有 2 个蓝牙芯片的电路板。一个作为专用 iBeacon 芯片,另一个作为永久 connected/paired/auth 和绑定芯片。这样就不需要监视任何定时的连接和断开连接事件(或者更糟的是……已解决的竞争条件)。在 iOS 中等待设备断开连接并不是真正的断开连接,而是当 iOS 系统认为它已断开连接时(在 phone 方面)。外围系统内部发生的事情描绘了一幅截然不同的画面...

这种 2 芯片方法使开发方面的工作变得更加轻松,因为现在只要您需要唤醒应用程序来处理某些事情,您就可以重新启动 iBeacon 设备并接收适当的事件。

旁注: 使用 iBeacon 时,didEnterRegion 方法几乎立即触发,而 didExitRegion 有时可能需要 30 秒或更长时间才能触发。因此,如果您需要立即解决信标检测问题,您应该尝试确保 iBeacon 正在打开而不是关闭电源……如果可能的话。