Domanda

I have an external device that communicates via Bluetooth with an iPhone Application that has support for iOS6+.

The problem is that I need to write more than 20 bytes to a characteristic and from what I've read and tried this is not possible using BLE.

Here is a basic structure of my method:

NSData * payload = ... //53 bytes, last 2 bytes CRC
[peripheral writeValue:payload forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];

The error I get when sending >20 bytes is CBErrorOperationCancelled (code 5) and CBErrorConnectionTimeout (code 6). I believe this is normal.

I divided the data in chunks of 20 bytes (example here: https://github.com/RedBearLab/iOS/issues/8) and the data is not written well on the device:

NSData * chunk1 = ... //first 20 bytes
NSData * chunk2 = ... //next 20 bytes
...
NSData * chunkN = ... //remaining bytes + CRC from whole data

[peripheral writeValue:chunk1 forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
[peripheral writeValue:chunk2 forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
...
[peripheral writeValue:chunkN forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];

I think the external device treats each byte array, not the whole data.

Also, I tried to split the payload data in chunks of 18 bytes and append the CRC to each chunk of bytes I send. This got me the same result as in appending CRC to the last chunk of data.

In the Android version of the application the whole data is sent, so I know that the device can read >20 bytes on a single command.

My questions are:

  1. Is it possible to send the whole data in chunks to the external device without modifying the peripherals hardware / software?

  2. Is there a flag / signal byte in the first chunk of data that notifies the device the length of the whole message?

  3. I've read that in iOS 7 is possible to send a larger byte array. If I make support for iOS 7+ will it solve my problem?

  4. What alternatives do I have to CB?

Any help will be appreciated. Many thanks!

EDIT

When I try sending data in chunks like in the BTLE sample I get the following response:

// NSLog - data that is written on the peripheral
// Chunk 1 : <2047d001 0f002000 315b0011 b4425543 41524553>
// Chunk 2 : <54202020 20202020 20202020 20202020 20202020>
// Chunk 3 : <20202020 2009059b 56210988 b9b50408 02c7123d>

// Write to peripheral
[self.twCurrentPeripheral writeValue:chunk1 forCharacteristic:self.twCharacteristic type:CBCharacteristicWriteWithoutResponse];
[self.twCurrentPeripheral writeValue:chunk2 forCharacteristic:self.twCharacteristic type:CBCharacteristicWriteWithoutResponse];
[self.twCurrentPeripheral writeValue:chunk3 forCharacteristic:self.twCharacteristic type:CBCharacteristicWriteWithResponse];

// NSLog - Response from peripheral
// Data update char : <20470000 04d00101 00ab42>
// Data update char : <204700>
// Data update char : <0004d001 0100ab42>
// Data update char : <204700>
// Data update char : <0504d001 032c6bcf>

The correct response should be (like in the Android version):

// Response <20470000 04d00101 00ab42>
// Response <20470000 04d00105 006786>
È stato utile?

Soluzione 2

You need to chunk the data in 20 byte length pieces, you got that part right. If you use the "write with response" method, then before sending the next piece of data, you should wait for the peripheral:didWriteValueForCharacteristic:error: callback to happen on your peripheral delegate before sending the next piece. In case of "write without response", you should wait before sending out the next chunk. The stuff you add in the in the writeValue call will be buffered. If the buffer is full, then your call will be dropped.

Altri suggerimenti

You need to send the data in 20 bytes chanks. Each packet should be at the size of 20 bytes. The other side (the BLE central) should accept the packets and save them until he gets all the packets he was waiting for. For this to happen you will have to create some kind of protocol: Sending the type of message then the length of the message in bytes and the centeral should read this header and then save the "length" bytes he is waiting for in this message and then parse the entire data.

Note that IOS might fail sending some of the packets when there are many packets to send very fast, so when calling

 success = [self.peripheral updateValue:chunk forCharacteristic:myChar onSubscribedCentrals:nil];

success will tell you if the send was successful, if it was not you need to resend this packet. in that case you should implement the IOS BLE protocol CBPeripheralManagerDelegate

and at the method peripheralManagerIsReadyToUpdateSubscribers you should retry sending the same packet again.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top