【问题标题】:ReadRSSI doesn't call the delegate methodReadRSSI 不调用委托方法
【发布时间】:2014-11-21 13:42:19
【问题描述】:

自从 iOS 8 更新以来我遇到了一个问题,现在我的应用程序已连接到 BLE 设备并通过计时器和 ReadRSSI 方法定期读取 RSSI。

readRSSI 方法被调用(使用断点检查),所以在此之前一切都很好。

根据文档调用readRSSI 应该触发回调

- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error

但是,并不是每次都调用这个委托方法。但是当我关闭和打开手机蓝牙时,我会返回 RSSI 更新。有没有人遇到过这个问题?我该如何解决?

【问题讨论】:

  • 尝试按照my answer to a similar question连接外围设备。
  • 我必须重置我的 iPhone 才能让它再次工作,同时按住电源和主页按钮。

标签: ios bluetooth ios8 bluetooth-lowenergy core-bluetooth


【解决方案1】:

我也遇到了同样的问题,一开始以为是我的错,后来发现真的很奇怪。

我编写了类似的程序,使用 iPhone 连接到 BLE 信标,并使用 [CBPeripheral readRSSI] 获取信号强度。当 BLE 信标第一次连接到我的 iPhone 时,一切都很顺利。但是,如果它断开连接并重新连接,则 readRSSI 方法将不再被调用。 只有在我重新启动 iPhone 上的蓝牙后,问题才会得到解决。

我在调试模式下运行程序,一步一步地,令我惊讶的是,我发现一点问题都没有。即使我断开了这么多次重新连接,readRSSI方法仍然可以正常调用。

希望这可能会有所帮助。我也在等待这个奇怪的事情的答案。

【讨论】:

  • 感谢您的回答,我刚刚填写了一份 Apple 错误报告,我会及时通知您
  • 所以 Apple 刚刚关闭了我的 Bug 作为 #18476971 的副本,但我无法访问它,所以我不知道 Apple 的调查
  • 我想他们已经意识到了这个问题,看来BLE在iOS8中有很多问题。
【解决方案2】:

我最近遇到了这个问题,我遇到了多个导致它的问题。以下是清单形式的解决方案,从最简单到最复杂:

  1. CBCentralManager 不会强烈引用 peripheral,您需要自己保留它。
  2. 确保您确实是peripheral.delegate
  3. 确保您正在实施新方法 peripheral(peripheral:didReadRSSI:error:) 而不是旧方法。
  4. iOS 8.0.2 引入了上述方法的问题,8.1、8.2、8.3 之后的任何版本都可以正常工作(@Gamma-Point 提到的内容)。
  5. 您只能readRSSI 用于连接到您的中心的设备,因此:
    1. 对于通过发现检索到的设备,您可以在执行scanForPeripheralsWithServices(_:options:) 时传递[CBCentralManagerScanOptionAllowDuplicatesKey : true]。如this answer 所示。
    2. 另外,central.retrieveConnectedPeripheralsWithServices 方法有一个陷阱。此方法返回“已连接”设备,但 readRSSI 和服务发现在您实际调用它们之前都有效,因此即使它们已连接到 iPhone/iPad/AppleWatch,它们也不会连接到您的 中心,很烦人。

最后一个对我来说是个大问题,我希望“选择最近”连接或发现的设备,但无法让 RSSI 更新它们。文档也没有说什么。

我最终做的是构建一个大字典,其中包含由[UUID : Device] 索引的所有设备(设备是CBPeripheral 的包装器)。通过发现添加的设备通过 de discover 方法更新其 RSSI,连接的设备通过蓝牙队列上的 GCD 计时器调用 readRSSI 并更新它们自己的 RSSI 读数。

【讨论】:

    【解决方案3】:

    我有 8.0,它工作正常。

    -(void) startScanForRSSI{
    
        timerRSSI = [NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(detectRSSI) userInfo:nil repeats:YES];
    
    }
    
    - (void)detectRSSI {
    
        if (state == ...) {
            peripheral.delegate = self;
            [peripheral readRSSI];
        } else {
            if (timerRSSI && [timerRSSI isValid])  {
                [timerRSSI invalidate];
            }
        }
    }
    
    
    
    - (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error {
    
    
    
        NSLog(@"Got RSSI update: %4.1f", [peripheral.RSSI doubleValue]);
    
    
        NSNumber *rssiNum = peripheral.RSSI;
    }
    

    由于上述在 iOS 8 中已被弃用,尝试其他委托,将报告。

    -(void) peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error {
         NSLog(@"Got RSSI update in didReadRSSI : %4.1f", [RSSI doubleValue]);
    }
    

    这似乎是一个 OSX 委托方法。 Apple 可能很快会在 iOS 中为 RSSI 添加一些东西。

    在 iOS 8.0 中,didReadRSSI 可以正常工作。在 8.0.2 文档中,它没有在 iOS 下列出。

    如果我将这两种方法都放在 iOS 8 中调用 didReadRSSI 和在 iOS 7 中调用 peripheralDidUpdateRSSI。

    因此,在 Apple 为 RSSI 提供一些东西之前,请不要更新到 iOS 8.0.2。

    有人试用过 iOS 8.1 测试版吗?

    扫描设备时似乎无法读取 RSSI。如果已启动对 [CBCentralManager scanForPeripheralsWithServices...] 的调用,则不会发生 ReadRSSI 的影响(不调用委托)。但是如果发出 [CBCentralManager stopScan],ReadRSSI 就会开始响应。

    另请注意:设备必须处于连接状态才能发出命令,否则您将获得: CoreBluetooth[API MISUSE] CBPeripheral 只能在连接状态下接受命令。

    【讨论】:

      猜你喜欢
      • 2012-09-22
      • 2017-02-14
      • 2011-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多