通过 BLE 通知接收数据包

Posted

技术标签:

【中文标题】通过 BLE 通知接收数据包【英文标题】:Receive data packets via BLE Notifications 【发布时间】:2014-06-11 19:54:47 【问题描述】:

当通过 BLE 通知接收多个数据包时,ios 只允许我访问发送的最终数据包。我正在使用 YMSCoreBluetooth 连接到具有多个服务的 BLE 外围设备,每个服务都有多个特征。我连接到外围设备,发现服务并毫无问题地发现这些服务的特征。我的目标是订阅某个特征的通知,并通过通知接收一系列数据包。我的订阅成功,我可以通过在我的代码中使用 NSLogs 看到我正在接收包含数据的通知。问题是当我去访问每个通知中的数据时,每个通知只给我发送的最后一个数据包中包含的数据。

我的接收通知代码如下:

- (void)notifyCharacteristicHandler:(YMSCBCharacteristic *)characteristic error:(NSError *)error

    if (error) 
        NSLog(@"Error: Error in handling notification.\n%@", error);
    
    else if ([characteristic.name isEqualToString:@"InterestingChar"]) 
        if (self.firstNotify) 
            self.mutableData = [[NSMutableData alloc] init];
            self.firstNotify = NO;
        
        NSData *data = [[NSData alloc] init];
        data = characteristic.cbCharacteristic.value;

        [self.mutableData appendData:data];

        self.notifyCounter++;
        NSLog(@"Notify received! Count: %ld \nData =%@",(long)self.notifyCounter,self.mutableData);
    
    else NSLog(@"Other notification received");

例如,如果我收到 5 条包含以下数据的通知:

1 个 ababababa

2 bcbcbcbcbc

3 cdcdcdcdcd

4 dedededede

5 效果

我的 NSLog 将为第一个通知数据打印 efefefefef,第二个为 efefefefef efefefefef,依此类推,为每个后续通知附加最后一个数据值。

我正在尝试使用 BLE 从外围设备尽快发送通知。连接间隔在 20 毫秒到 40 毫秒之间(iOS 要求范围至少为 20 毫秒),每个连接间隔发送三个数据包。

编辑:

Paulw11 的建议效果很好。我通过修改 YMSCB 的“didUpdateValueForCharacteristic”方法来解决该问题,以获取特征的值并将其与指向特征本身的指针一起传递给“notifyCharacteristicHandler”方法。修改后的方法现在如下所示:

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error 
    __weak YMSCBPeripheral *this = self;
    NSData *value = characteristic.value;
    _YMS_PERFORM_ON_MAIN_THREAD(^
        YMSCBService *btService = [this findService:characteristic.service];
        YMSCBCharacteristic *yc = [btService findCharacteristic:characteristic];

        if (yc.cbCharacteristic.isNotifying) 
            [btService notifyCharacteristicHandler:yc value:value error:error];

         else 
            if ([yc.readCallbacks count] > 0) 
                [yc executeReadCallback:characteristic.value error:error];
            
        

        if ([this.delegate respondsToSelector:@selector(peripheral:didUpdateValueForCharacteristic:error:)]) 
            [this.delegate peripheral:peripheral didUpdateValueForCharacteristic:characteristic error:error];
        
    );

您显然还需要修改“notifyCharacteristicHandler”方法以接受新参数。

【问题讨论】:

NSData 的 alloc/init 没用,因为你做了 data = characteristic.cbCharacteristic.value。另外,它不应该没有“characeteristic.value”吗?错字? 它是一个YMSCBCharacteristic,它有一个CBCharacteristic作为一个属性,而它又是一个值 【参考方案1】:

查看 YMSCoreBluetooth 库的内部 didUpdateValueForCharacteristic 委托方法,它使用“在主线程上执行”将数据发送到您的方法,并且它不捕获数据 - 它只是发送对特征的引用。此外,它通过在主线程上的数组中执行线性搜索来对特征执行“findCharacteristic”,即使这可以在当前线程上进入委托方法时立即完成。当然,这不会是一个非常大的数组,但似乎创建这个库时并没有考虑到性能。

我怀疑您有时间问题 - 到您的方法执行时,特征中的数据已被覆盖。如果您可以控制外围设备,请立即放慢速度进行测试,看看问题是否消失。

如果它与时间相关,那么您可以尝试直接的 Core-Bluetooth 实现,或者尝试修改 YMSCoreBluetooth 以便它更早地捕获数据 - 也许如果它在 didUpdateValueForCharacteristic 的开头创建了外围设备的副本,并且将其发送到您的方法即可。

【讨论】:

你完全正确。发布后,我按照您在此处的建议放慢了外围通知的速度,并且数据开始按预期以相当低的速度通过。我一直在通过 YMS 寻找解释,但还没有找到你做了什么。谢谢!当我弄清楚我需要哪些修复以供后代使用时,我会编辑原始帖子。

以上是关于通过 BLE 通知接收数据包的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 上从 nRF52 ARM 接收 BLE 数据包的速度很慢

蓝牙 GATT 向 BLE 设备发送数据

ESP32 BLE蓝牙 微信小程序通信发送大于20字符数据

在 Android 中不接收 BLE 通知

bluetooth4.0 ble 接收短信通知

无法取消注册 ble 通知的 dbus 信号