1

I am having an issue with latency when connecting to a bluetooth accessory using the External Accessory Framework. When sending data I get the following custom output in the console:

if( [stream hasSpaceAvailable] )
{
   NSLog( @"Space avail" );
}
else {
    NSLog(@"No space");
}
while( [stream hasSpaceAvailable] && ( [_outputBuffer length] > 0 ) )
{
    /* write as many bytes as possible */
    NSInteger written = [stream write:[_outputBuffer bytes] maxLength:[_outputBuffer length]];
    NSLog( @"wrote %i out of %i bytes to the stream", written, [_outputBuffer length] );
if( written == -1 )
    {
        /* error, bad */
        Log( @"Error writing bytes" );
        break;
    }
    else if( written > 0 )
    {
        /* remove the bytes from the buffer that were written */
        Log( @"erasing %i bytes", written );
        [_outputBuffer replaceBytesInRange:NSMakeRange( 0, written ) withBytes:nil length:0 ];
    }
}

This results with the following output where immediate pack buffer is the payload.

immediate pack buffer-> 040040008
Space avail
wrote 10 out of 10 bytes to the stream
immediate pack buffer-> 040010005
No space
immediate pack buffer-> 030040007
No space
wrote 20 out of 20 bytes to the stream
immediate pack buffer-> 030010004
No space
immediate pack buffer-> 040000004
Space avail
wrote 20 out of 20 bytes to the stream
immediate pack buffer-> 030000003
Space avail
wrote 10 out of 10 bytes to the stream
immediate pack buffer-> 040040008
Space avail
wrote 10 out of 10 bytes to the stream

Notice how it continually has "No Space" written which means that the method hasSpaceAvailable is returning false and forcing the data to be buffered until it returns true.

1) What I need to know is why is the happening? Is it waiting for an Ack from the BT hardware? If so how do you removing this blocking?

2) How do you do this so it sends immediately and we basically stream the data in real time without buffering?

3) Is there a hidden API method that will disable this blocking?

This is a real problem because there cannot be any delay/latency in sending the data to the device, it must be sent immediately in order for the hardware to be in sync with the iPhone commands. Please help.

andy k
  • 111
  • 2
  • 5

3 Answers3

2

What you're asking for is impossible with most hardware (which will finish sending the current packet before starting the next one), and impossible with the usual "stream" paradigm (which requires that data is received in order, so is bandwidth-limited).

It is also physically impossible to have zero latency unless the source and destination are coincident.

The actual problem seems to be that the underlying stream only queues one packet at a time, even if the packet is only 10 bytes long. I don't know why; possibly because it's intended as a very simple protocol.

The usual way of dealing with such a queue is to register for the appropriate delegate callbacks and send as much data as you can when the stream has space available, instead of waiting for the next time you attempt to send data (which appears to be what you're doing).

tc.
  • 33,468
  • 5
  • 78
  • 96
0

The problem is the HandleEvent delegate function is an asynchronous call.So every time it is not hitting the delegate. What you can do is, have the collections of commands in an array at once, open the session, call the writeData Function.What happens here is, once the write data is called, you don't need the HandleEvent Function to be hit for every command. Have a count incremented in writeData function for the count of array items,Until count == arrayItems, Delegate is not hit..

So all the commands from list are sent one by one.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
-1

I am facing the same issue but in different scenario.

Scenario: iPhone app is able to communicate the PED when gets connected for the first time. But when PED battery dies or switched off and then switched on, app is not able to communicate with PED in spite of active session and valid output stream. Output steam says its does not have spece to write anything.

Solution: When PED gets switched, app gets notified, and at that moment I make the app to kill EASession and create it again when PED gets connection. Not sure whether it is best solution. Please suggest another solution if there is any.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
deepax11
  • 199
  • 3
  • 7