iOS 在 BLE 上写入数据时出现未知错误
Getting Unknown Error while writing data on BLE in iOS
我正在尝试开发 iOS 应用程序,它正在检测 BLE 设备并需要调用写入命令。我可以成功连接到 BLE 设备并发现它的服务和特性。但是我在连接的外围设备上写入数据时遇到未知错误。下面是我写的代码:
发现的特征:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
NSArray *characteristics = [service characteristics];
if (peripheral != self.peripheral) {
NSLog(@"Wrong Peripheral.\n");
return ;
}
if (error != nil) {
NSLog(@"Error %@\n", error);
return ;
}
for (CBCharacteristic *characteristic in characteristics) {
if ([[characteristic UUID] isEqual:RWT_POSITION_CHAR_UUID]) {
self.positionCharacteristic = characteristic;
}
}
}
这里是BLE设备写数据的函数
- (void)writeCommand{
// See if characteristic has been discovered before writing to it
if (!self.positionCharacteristic) {
return;
}
NSString *cmd1=@"CQ+WHORU\r";
NSData *dataToWrite = [cmd1 dataUsingEncoding:NSUTF8StringEncoding];
CBCharacteristic *chr = self.positionCharacteristic;
NSLog(@"%@,%lu...%@",chr.UUID,chr.properties,chr);
NSInteger dataSize = [[NSByteCountFormatter stringFromByteCount:dataToWrite.length countStyle:NSByteCountFormatterCountStyleFile] integerValue];
if (dataSize > 130) {
NSLog(@"Cannot send more than 130 bytes");
}
else
{
[self.peripheral writeValue:dataToWrite forCharacteristic:self.positionCharacteristic type:CBCharacteristicWriteWithResponse];
}
}
- (void)peripheral:(CBPeripheral *)peripheral
didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error
{
if (error)
{
NSLog(@"Error writing characteristic value: %@", [error localizedDescription]);
}
else
{
NSLog(@"Successfully writing characteristic value");
}
}
在 "didWriteValueForCharacteristic" 委托方法中出现以下错误:
Error writing characteristic value: Unknown error.
此错误的可能原因是什么?
此外,如果我试图定义在 BLE 设备上发送数据的特性,例如:
CBMutableCharacteristic *writeChar = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:@"ffe1"] properties:CBCharacteristicPropertyWriteWithoutResponse|CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsWriteable|CBAttributePermissionsReadable];
int8_t cmd = *[cmd1 UTF8String];
NSData *data = [NSData dataWithBytes:&cmd length:sizeof(cmd)];
NSInteger dataSize = [[NSByteCountFormatter stringFromByteCount:dataToWrite.length countStyle:NSByteCountFormatterCountStyleFile] integerValue];
if (dataSize > 130) {
NSLog(@"Cannot send more than 130 bytes");
}
else
{
[self.peripheral writeValue:dataToWrite forCharacteristic:writeChar type:CBCharacteristicWriteWithResponse];
// [self.peripheral writeValue:dataToWrite forCharacteristic:writeChar type:CBCharacteristicWriteWithResponse];
}
然后我收到这个错误:
**CoreBluetooth[WARNING] CBMutableCharacteristic: 0x1552a270 UUID = Unknown (<ffe1>),Value = (null), Properties = 0x14, Permissions = 0x3, Descriptors = (null), SubscribedCentrals = (
)> is not a valid characteristic for peripheral <CBPeripheral: 0x15549930 identifier = FC71890D-9F71-5E16-086D-D491E1EF7599, Name = " DEMOBLE1", state = connected**
我在开发 iOS 应用程序(作为中央设备)和 BLE 设备固件(作为外围设备)时看到了这个错误。当我 changed/modified BLE 外设的特性时会发生这种情况。
iOS 似乎在连接后缓存有关服务和特征的信息。每当我将 build/download 新固件添加到设备时,我都可以通过更新外围设备的蓝牙地址来解决这个问题。
首先,您使用的是CBCentralManager
,对吧?
确保您以正确的方式进行操作:
使用CBCentralManager
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
当外设连接时检测
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
if (connectedDevice) // make sure you disconnect previous device
[self.centralManager cancelPeripheralConnection:connectedDevice];
connectedDevice = [peripheral retain];
connectedDevice.delegate = self;
[connectedDevice discoverServices:nil]; // this will discover all kind of services
}
如果连接过程中出现问题,您会在这里找到(例如,电池电量不足)
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"Did fail to connect: %@",error.description);
connectedDevice = nil;
}
成功连接的 BLE 出现问题(例如,电池电量低,用户关闭了设备)
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"Disconnected: %@",error.description);
connectedDevice = nil;
}
在这里,您可以找到可用的服务
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog([NSString stringWithFormat:@"%@",[advertisementData description]]);
}
6.
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
NSString *messtoshow;
switch (central.state) {
case CBCentralManagerStatePoweredOn:
{
[NSString stringWithFormat:@"Bluetooth is currently powered on and available to use."];
CBUUID *heartRate = [CBUUID UUIDWithString:HRM_SERVICE_UUID];
CBUUID *batteryLevel = [CBUUID UUIDWithString:BATTERY_LIFE_SERVICE_UUID];
NSDictionary *scanOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
[self.centralManager scanForPeripheralsWithServices:[NSArray arrayWithObjects:heartRate,batteryLevel,nil] options:scanOptions];
break;
}
}
}
从现在开始,您可以实现CBPeripheralDelegate
方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
for (CBService *service in peripheral.services) {
NSLog(@"Discovered service: %@", service.UUID);
[peripheral discoverCharacteristics:nil forService:service];
}
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
if ([service.UUID isEqual:[CBUUID UUIDWithString:HRM_SERVICE_UUID]]) {
for (CBCharacteristic *aChar in service.characteristics)
{
if ([aChar.UUID isEqual:[CBUUID UUIDWithString:HRM_MEASUREMENT_CHARACTERISTIC_UUID]]) {
[connectedDevice setNotifyValue:YES forCharacteristic:aChar];
}
}
}
if ([service.UUID isEqual:[CBUUID UUIDWithString:BATTERY_LIFE_SERVICE_UUID]]) {
for (CBCharacteristic *aChar in service.characteristics)
{
if ([aChar.UUID isEqual:[CBUUID UUIDWithString:BATTERY_LEVEL_CHARACTERISTIC_UUID]]) {
[connectedDevice readValueForCharacteristic:aChar];
}
}
}
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
NSError* err = nil;
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:HRM_MEASUREMENT_CHARACTERISTIC_UUID]]) {
NSData *data = [characteristic value];
}
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:BATTERY_LEVEL_CHARACTERISTIC_UUID]]) {
}
}
这应该可以正常工作。我已经按照同样的方式实现了,没有任何问题。希望对您有所帮助。
当您写入数据时,您正在请求响应 (CBCharacteristicWriteWithResponse
)。
如果您正在写入的特征没有设置属性 CBCharacteristicPropertyWrite
,写入将失败,但只支持无响应写入(CBCharacteristicPropertyWriteWithoutResponse
)。
if ((self.positionCharacteristic.properties & CBCharacteristicPropertyWrite) == CBCharacteristicPropertyWrite) {
// Responses are available, so write with response.
[self.peripheral writeValue:dataToWrite forCharacteristic:self.positionCharacteristic type:CBCharacteristicWriteWithResponse];
}
else if ((self.positionCharacteristic.properties & CBCharacteristicPropertyWriteWithoutResponse) == CBCharacteristicPropertyWriteWithoutResponse) {
// Responses are not available.
// Write with response is going to fail, so write without response.
[self.peripheral writeValue:dataToWrite forCharacteristic:self.positionCharacteristic type:CBCharacteristicWriteWithoutResponse];
}
我正在尝试开发 iOS 应用程序,它正在检测 BLE 设备并需要调用写入命令。我可以成功连接到 BLE 设备并发现它的服务和特性。但是我在连接的外围设备上写入数据时遇到未知错误。下面是我写的代码:
发现的特征:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
NSArray *characteristics = [service characteristics];
if (peripheral != self.peripheral) {
NSLog(@"Wrong Peripheral.\n");
return ;
}
if (error != nil) {
NSLog(@"Error %@\n", error);
return ;
}
for (CBCharacteristic *characteristic in characteristics) {
if ([[characteristic UUID] isEqual:RWT_POSITION_CHAR_UUID]) {
self.positionCharacteristic = characteristic;
}
}
}
这里是BLE设备写数据的函数
- (void)writeCommand{
// See if characteristic has been discovered before writing to it
if (!self.positionCharacteristic) {
return;
}
NSString *cmd1=@"CQ+WHORU\r";
NSData *dataToWrite = [cmd1 dataUsingEncoding:NSUTF8StringEncoding];
CBCharacteristic *chr = self.positionCharacteristic;
NSLog(@"%@,%lu...%@",chr.UUID,chr.properties,chr);
NSInteger dataSize = [[NSByteCountFormatter stringFromByteCount:dataToWrite.length countStyle:NSByteCountFormatterCountStyleFile] integerValue];
if (dataSize > 130) {
NSLog(@"Cannot send more than 130 bytes");
}
else
{
[self.peripheral writeValue:dataToWrite forCharacteristic:self.positionCharacteristic type:CBCharacteristicWriteWithResponse];
}
}
- (void)peripheral:(CBPeripheral *)peripheral
didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error
{
if (error)
{
NSLog(@"Error writing characteristic value: %@", [error localizedDescription]);
}
else
{
NSLog(@"Successfully writing characteristic value");
}
}
在 "didWriteValueForCharacteristic" 委托方法中出现以下错误:
Error writing characteristic value: Unknown error.
此错误的可能原因是什么?
此外,如果我试图定义在 BLE 设备上发送数据的特性,例如:
CBMutableCharacteristic *writeChar = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:@"ffe1"] properties:CBCharacteristicPropertyWriteWithoutResponse|CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsWriteable|CBAttributePermissionsReadable];
int8_t cmd = *[cmd1 UTF8String];
NSData *data = [NSData dataWithBytes:&cmd length:sizeof(cmd)];
NSInteger dataSize = [[NSByteCountFormatter stringFromByteCount:dataToWrite.length countStyle:NSByteCountFormatterCountStyleFile] integerValue];
if (dataSize > 130) {
NSLog(@"Cannot send more than 130 bytes");
}
else
{
[self.peripheral writeValue:dataToWrite forCharacteristic:writeChar type:CBCharacteristicWriteWithResponse];
// [self.peripheral writeValue:dataToWrite forCharacteristic:writeChar type:CBCharacteristicWriteWithResponse];
}
然后我收到这个错误:
**CoreBluetooth[WARNING] CBMutableCharacteristic: 0x1552a270 UUID = Unknown (<ffe1>),Value = (null), Properties = 0x14, Permissions = 0x3, Descriptors = (null), SubscribedCentrals = (
)> is not a valid characteristic for peripheral <CBPeripheral: 0x15549930 identifier = FC71890D-9F71-5E16-086D-D491E1EF7599, Name = " DEMOBLE1", state = connected**
我在开发 iOS 应用程序(作为中央设备)和 BLE 设备固件(作为外围设备)时看到了这个错误。当我 changed/modified BLE 外设的特性时会发生这种情况。
iOS 似乎在连接后缓存有关服务和特征的信息。每当我将 build/download 新固件添加到设备时,我都可以通过更新外围设备的蓝牙地址来解决这个问题。
首先,您使用的是CBCentralManager
,对吧?
确保您以正确的方式进行操作:
使用
CBCentralManager
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
当外设连接时检测
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { if (connectedDevice) // make sure you disconnect previous device [self.centralManager cancelPeripheralConnection:connectedDevice]; connectedDevice = [peripheral retain]; connectedDevice.delegate = self; [connectedDevice discoverServices:nil]; // this will discover all kind of services }
如果连接过程中出现问题,您会在这里找到(例如,电池电量不足)
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{ NSLog(@"Did fail to connect: %@",error.description); connectedDevice = nil; }
成功连接的 BLE 出现问题(例如,电池电量低,用户关闭了设备)
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{ NSLog(@"Disconnected: %@",error.description); connectedDevice = nil; }
在这里,您可以找到可用的服务
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { NSLog([NSString stringWithFormat:@"%@",[advertisementData description]]); }
6.
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
NSString *messtoshow;
switch (central.state) {
case CBCentralManagerStatePoweredOn:
{
[NSString stringWithFormat:@"Bluetooth is currently powered on and available to use."];
CBUUID *heartRate = [CBUUID UUIDWithString:HRM_SERVICE_UUID];
CBUUID *batteryLevel = [CBUUID UUIDWithString:BATTERY_LIFE_SERVICE_UUID];
NSDictionary *scanOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
[self.centralManager scanForPeripheralsWithServices:[NSArray arrayWithObjects:heartRate,batteryLevel,nil] options:scanOptions];
break;
}
}
}
从现在开始,您可以实现
CBPeripheralDelegate
方法- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { for (CBService *service in peripheral.services) { NSLog(@"Discovered service: %@", service.UUID); [peripheral discoverCharacteristics:nil forService:service]; } } - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { if ([service.UUID isEqual:[CBUUID UUIDWithString:HRM_SERVICE_UUID]]) { for (CBCharacteristic *aChar in service.characteristics) { if ([aChar.UUID isEqual:[CBUUID UUIDWithString:HRM_MEASUREMENT_CHARACTERISTIC_UUID]]) { [connectedDevice setNotifyValue:YES forCharacteristic:aChar]; } } } if ([service.UUID isEqual:[CBUUID UUIDWithString:BATTERY_LIFE_SERVICE_UUID]]) { for (CBCharacteristic *aChar in service.characteristics) { if ([aChar.UUID isEqual:[CBUUID UUIDWithString:BATTERY_LEVEL_CHARACTERISTIC_UUID]]) { [connectedDevice readValueForCharacteristic:aChar]; } } } } - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { NSError* err = nil; if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:HRM_MEASUREMENT_CHARACTERISTIC_UUID]]) { NSData *data = [characteristic value]; } if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:BATTERY_LEVEL_CHARACTERISTIC_UUID]]) { } }
这应该可以正常工作。我已经按照同样的方式实现了,没有任何问题。希望对您有所帮助。
当您写入数据时,您正在请求响应 (CBCharacteristicWriteWithResponse
)。
如果您正在写入的特征没有设置属性 CBCharacteristicPropertyWrite
,写入将失败,但只支持无响应写入(CBCharacteristicPropertyWriteWithoutResponse
)。
if ((self.positionCharacteristic.properties & CBCharacteristicPropertyWrite) == CBCharacteristicPropertyWrite) {
// Responses are available, so write with response.
[self.peripheral writeValue:dataToWrite forCharacteristic:self.positionCharacteristic type:CBCharacteristicWriteWithResponse];
}
else if ((self.positionCharacteristic.properties & CBCharacteristicPropertyWriteWithoutResponse) == CBCharacteristicPropertyWriteWithoutResponse) {
// Responses are not available.
// Write with response is going to fail, so write without response.
[self.peripheral writeValue:dataToWrite forCharacteristic:self.positionCharacteristic type:CBCharacteristicWriteWithoutResponse];
}