2013-07-24 167 views
6

我正在使用CoreBlueTooth框架寫入Peripheral的可寫特徵之一。我正在執行「didWriteValueForCharacteristic:錯誤:」中央的代理總是返回我下面的錯誤。雖然我收到了有關外設的數據。CoreBlueTooth:即使將數據寫入可寫特徵也會出錯

Error Domain=CBErrorDomain Code=0 "Unknown error." UserInfo=0x166762e0 {NSLocalizedDescription=Unknown error.} 

在我的代碼中,我的self.data是一個帶有3個鍵和值的NSDictionary。

// Central 

- (void)centralManagerDidUpdateState:(CBCentralManager *)iCentral { 
    if (iCentral.state != CBCentralManagerStatePoweredOn) { 
     return; 
    } 

    [self.centralManager scanForPeripheralsWithServices:self.peripheralServices options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES}]; 
} 


- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)iPeripheral advertisementData:(NSDictionary *)iAdvertisementData RSSI:(NSNumber *)iRSSI { 
    if (self.discoveredPeripheral != iPeripheral) { 
     // Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it 
     self.discoveredPeripheral = iPeripheral; 

     // Connect to the discovered peripheral 
     [self.centralManager connectPeripheral:iPeripheral options:nil]; 
    } 
} 

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)iPeripheral advertisementData:(NSDictionary *)iAdvertisementData RSSI:(NSNumber *)iRSSI { 
    if (self.discoveredPeripheral != iPeripheral) { 
     // Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it 
     self.discoveredPeripheral = iPeripheral; 

     // Connect to the discovered peripheral 
     [self.centralManager connectPeripheral:iPeripheral options:nil]; 
    } 
} 


// We've connected to the peripheral, now we need to discover the services and characteristics to find the 'writeable' characteristic. 
- (void)centralManager:(CBCentralManager *)iCentral didConnectPeripheral:(CBPeripheral *)iPeripheral { 
    // Stop scanning 
    [self.centralManager stopScan]; 

    // Make sure we get the discovery callbacks 
    iPeripheral.delegate = self; 

    // Search only for services that match our UUID 
    [iPeripheral discoverServices:self.peripheralServices]; 
} 


- (void)peripheral:(CBPeripheral *)iPeripheral didDiscoverServices:(NSError *)iError { 
    if (iError) { 
     [self cleanup]; 
     return; 
    } 

    // Loop through the newly filled peripheral.services array, just in case there's more than one. 
    for (CBService *service in iPeripheral.services) { 
     [iPeripheral discoverCharacteristics:@[self.writeableCharactersticsUUID] forService:service]; 
    } 
} 


// Write the data into peripheral's characterstics 
- (void)peripheral:(CBPeripheral *)iPeripheral didDiscoverCharacteristicsForService:(CBService *)iService error:(NSError *)iError { 
    if (iError) { 
     [self cleanup]; 

     return; 
    } 

    // Find out the writable characterstics 
    for (CBCharacteristic *characteristic in iService.characteristics) { 
     if ([characteristic.UUID isEqual:self.writeableCharactersticsUUID]) { 
      NSData *dataToWrite = [NSJSONSerialization dataWithJSONObject:self.data options:0 error:nil]; 
      NSInteger dataSize = [[NSByteCountFormatter stringFromByteCount:dataToWrite.length countStyle:NSByteCountFormatterCountStyleFile] integerValue]; 
      if (dataSize > 130) { 
       NSLog(@"Cannot send more than 130 bytes"); 
       return; 
      } 

      [self.discoveredPeripheral writeValue:dataToWrite forCharacteristic:self.centralWriteableCharacteristic type:CBCharacteristicWriteWithResponse]; 

      break; 
     } 
    } 
} 


- (void)peripheral:(CBPeripheral *)iPeripheral didWriteValueForCharacteristic:(CBCharacteristic *)iCharacteristic error:(NSError *)iError { 
    NSLog(@"Error = %@", iError); 
} 


- (void)cleanup { 
    // Don't do anything if we're not connected 
    if (self.discoveredPeripheral.state != CBPeripheralStateConnected) { 
     return; 
    } 

    // If we've got this far, we're connected, but we're not subscribed, so we just disconnect 
    [self.centralManager cancelPeripheralConnection:self.discoveredPeripheral]; 
} 


// Peripheral 

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)iPeripheral { 
    if (iPeripheral.state != CBPeripheralManagerStatePoweredOn) { 
     return; 
    } 

    CBMutableCharacteristic *characteristic = [[CBMutableCharacteristic alloc] initWithType:iCID properties:CBCharacteristicPropertyWrite value:nil permissions:CBAttributePermissionsWriteable]; 

    CBMutableService *writableService = [[CBMutableService alloc] initWithType:iServiceId primary:YES]; 
    writableService.characteristics = @[characteristic]; 

    //[self.peripheralManager removeAllServices]; 
    [self.peripheralManager addService:writableService]; 
    [self.peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[iServiceId]}]; 
} 

- (void)peripheralManager:(CBPeripheralManager *)iPeripheral didReceiveWriteRequests:(NSArray *)iRequests { 
    CBATTRequest *aRequest = iRequests[0]; 
    NSData *aData = aRequest.value; 
    NSDictionary *aResponse = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:aData options:NSJSONReadingMutableContainers error:nil]; 

    NSLog(@"Received Data = %@", aResponse); 
} 

回答

9

我已經想通了。問題在於特徵類型。而不是「CBCharacteristicWriteWithResponse」我用「CBCharacteristicWriteWithoutResponse」,它的工作。

我沒有這個閱讀本後:

writeValue forCharacteristic writeType,該功能是用於寫入特性的裝置上的主要功能。 writeType屬性被設置爲無響應寫入或寫入響應。當使用響應寫入時,所有對外設的寫入都被緩存,而iOS設備正在等待收到ok響應和回調。當寫入沒有迴應時,數據不會被緩存。當使用需要低延遲的東西時,如RC車或直升機等,當使用帶響應的寫入時,這一點非常重要,iOS設備可能有時會滯後,這不會產生很好的響應......對於每次寫入,都會調用didWriteCharacteristic回調函數。

+0

我又有了這個確切同樣的問題一次次(不斷變化的固件要求)。我需要每次都谷歌:) – SJoshi

+0

我做了同樣的改變,但仍然沒有得到任何外設端的任何電話。我正在尋找PeripheralManager的'didReceiveWriteRequests'方法中的任何更新。我對麼 ? – Mrug

2

將此處留給其他人,但OP的答案不正確。

這是這裏提出的是,他並沒有此功能更新他的特點的錯誤:

- (void)peripheralManager:(CBPeripheralManager *)iPeripheral didReceiveWriteRequests:(NSArray *)iRequests { 
    CBATTRequest *aRequest = iRequests[0]; 
    NSData *aData = aRequest.value; 
    NSDictionary *aResponse = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:aData options:NSJSONReadingMutableContainers error:nil]; 


    NSLog(@"Received Data = %@", aResponse); 
} 

由於無特徵性發現更新,操作系統假定出現了錯誤,併產生一個錯誤。

CBMutableCharacteristic *characteristic = [[CBMutableCharacteristic alloc] initWithType:iCID properties:CBCharacteristicPropertyWrite value:nil permissions:CBAttributePermissionsWriteable]; 

該代碼實際上是設置爲與響應特性可寫,指定無響應的枚舉是:

CBCharacteristicPropertyWriteWithoutResponse 

希望這有助於其他人誰在這個跌倒。

4

錄製這爲後人:你必須作出反應,以防止錯誤:

- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests 
{ 
    // respond! 
    [peripheral respondToRequest:[requests objectAtIndex:0] withResult:CBATTErrorSuccess]; 
+0

不工作。仍然getitng數據無效 –

+0

工作正常。謝謝! – flame3