我有一个特征值,其中包含图像数据。在外围设备中,我设置的值是这样的:
_photoUUID = [CBUUID UUIDWithString:bPhotoCharacteristicUUID];
_photoCharacteristic = [[CBMutableCharacteristic alloc] initWithType:_photoUUID
properties:CBCharacteristicPropertyRead
value:Nil
permissions:CBAttributePermissionsReadable];
我的理解是,当请求此值时,将调用didReceiveReadRequest
回调:-(void) peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request {
if ([request.characteristic.UUID isEqual:_photoUUID]) {
if (request.offset > request.characteristic.value.length) {
[_peripheralManager respondToRequest:request withResult:CBATTErrorInvalidOffset];
return;
}
else {
// Get the photos
if (request.offset == 0) {
_photoData = [NSKeyedArchiver archivedDataWithRootObject:_myProfile.photosImmutable];
}
request.value = [_photoData subdataWithRange:NSMakeRange(request.offset, request.characteristic.value.length - request.offset)];
[_peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
}
}
}
这几乎来自Apple的文档。在didDiscoverCharacteristic
回调的中央端,我有以下代码:if ([characteristic.UUID isEqual:_photoUUID]) {
_photoCharacteristic = characteristic;
[peripheral readValueForCharacteristic:characteristic];
}
依次调用didUpdateValueForCharacteristic
回调:- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
NSLog(@"updated value for characteristic");
if ([characteristic.UUID isEqual:_photoUUID]) {
NSArray * photos = [NSKeyedUnarchiver unarchiveObjectWithData:characteristic.value];
}
}
所有的回调都被调用,但是当我尝试重新构造数组时,它被破坏了,因为并不是所有的数据都正确地传输了。我希望didRecieveReadRequest
回调被多次调用,每次都有不同的偏移量。但是,它仅被调用一次。我想知道是否有人知道我在做什么错?
最佳答案
我猜您正在突破特征长度的512字节限制。您需要转到特征订阅和更新处理中来解决此问题:
在中央:
-[CBPeripheral setNotifyValue:forCharacteristic]
(以YES作为通知值)订阅特征。 -peripheral:didUpdateValueForCharacteristic:error
中,每个更新要么是要追加的数据,要么是您选择在外围设备上用来表示数据结束的数据(为此,我使用了一个空的NSData
)。更新您的-peripheral:didUpdateValueForCharacteristic:error
代码,以便:NSMutableData
)。 -[CBPeripheral setNotifyValue:forCharacteristic]
来取消订阅该特性。 -peripheral:didUpdateNotificationStateForCharacteristic:error:
是管理初始化和以后使用读取大块的接收器的好地方。如果characteristic.isNotifying
更新为YES
,则您具有新的订阅;否则,您将获得新的订阅。如果它已更新为NO
,则说明您已经阅读完毕。此时,您可以使用NSKeyedUnarchiver取消存档数据。 在外围设备上:
-[CBMutableCharacteristic initWithType:properties:value:permissions]
中,确保properties
值包含CBCharacteristicPropertyNotify
。 -peripheralManager:central:didSubscribeToCharacteristic:
开始数据的分块发送,而不是-peripheral:didReceiveReadRequest:result:
。 central.maximumUpdateValueLength
。在iOS7上,在iPad 3和iPhone 5之间,我通常看到132个字节。如果要发送到多个中心,请使用最小公数值。 -updateValue:forCharacteristic:onSubscribedCentrals
的返回码;如果底层队列备份,则将返回NO
,并且您必须等待-peripheralManagerIsReadyToUpdateSubscribers:
上的回调后才能继续(我认为这是本来就很平滑的API中的毛刺之一)。根据您的处理方式,您可能会陷入困境,因为:-updateValue:forCharacteristic:onSubscribedCentrals:
的返回值,则很容易使自己陷入非显而易见的死锁。您要么要确保在每次调用-updateValue:forCharacteristic:onSubscribedCentrals:
之后就产生队列,请在与外设队列不同的队列上执行分块循环(-updateValue:forCharacteristic:onSubscribedCentrals:
将确保其工作在正确的位置进行)。否则您可能会变得更幻想;请注意这一点。 为了实际操作,WWDC 2012 Advanced Core蓝牙视频包含一个示例(共享VCard),其中涵盖了大部分内容。但是,它不检查更新的返回值,因此它们完全避免了#4的陷阱。
希望能有所帮助。
关于ios - 使用CoreBluetooth读取长特征值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19280429/