0



I try to use the Bluetooth communication synchronously. I send the data to the BTLE device and wait for the response to continue in the same method unless a timeout occurs.
I wanted to use NSRUNLOOP for the wait. However, I have the problem that only when the loop is completed, the data received in the meantime can be processed. So the loop seems to block the processing of the data.
The data is sent in a separate thread

... create command data
if (![self sendCommand:nd_commandData timeOutMesc:ui_timeOutMSec command:ui_command error:error])
{
    // Timeout
    return false;
}
... continue working with the received data

sending method with timeout:

-(BOOL)sendCommand:(NSData *)nd_sendData timeOutMesc:(uint)ui_timeOutMSec command:(UInt16)ui_command
{
  b_exitConditionSleep = false;
  b_timeOutOccurred = false;

  self.ni_totalResponseLength = 0;
  self.ni_expectedResponseLength = 0;

  // Clear buffer
  memset(&uia_receivedDataBytes[0], 0x00, sizeof(uia_receivedDataBytes));

  [[BTLE_Communicator sharedInstance] setDelegate:self];

// send data
  [[BTLE_Communicator sharedInstance] sendDataFromAppToBLEDevice:nd_sendData];

  BOOL b_rechTimeOut = true;
  NSDate *start = [NSDate date];
  NSTimeInterval timeInterval;
  uint ui_differenz;
  NSDate *loopUntil = [NSDate dateWithTimeIntervalSinceNow:0.01];

  while (!b_exitConditionSleep && [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:loopUntil])
  {
    loopUntil = [NSDate dateWithTimeIntervalSinceNow:0.01];

    timeInterval = [start timeIntervalSinceNow] * -1;
    ui_differenz = round(timeInterval * 1000);

    if (ui_differenz >= ui_timeOutMSec) {
        NSLog(@"Command: 0x%hX - Timeout reached: %u", ui_command, ui_differenz);
        b_rechTimeOut = false;
        b_timeOutOccurred = true;
        break;
    }
  }

  return b_rechTimeOut;
}

receiving method:

-(void)communicatorPeripheralDidReceiveResponseUARTData:(NSData *)nd_data
{
  NSLog(@"ResponseUARTData %@", nd_data);

  if (!b_timeOutOccurred)
  {
    b_exitConditionSleep = true;
    [self processResponseData:nd_data];
  }
}


Maybe someone has an indication of what I'm doing wrong.

Henning
  • 421
  • 2
  • 11
  • 22
  • 2
    You are trying to turn an inherently asynchronous process into a synchronous one. This is rarely a good idea. – Paulw11 Mar 29 '18 at 18:45

1 Answers1

0

what I'm doing wrong

You're trying to make an asynchronous task synchronous. That's the core problem. As for the specific reason why this particular pattern won't work, it is quite likely that the nested run loop is preventing a callback from being processed properly. Or it might be some other implementation detail that is incompatible with the conversion from asynchronous to synchronous.

Beyond an intellectual curiosity, there isn't much reason to figure out why.

Instead, call some kind of an update method from your implementation of communicatorPeripheralDidReceiveResponseUARTData:. This will allow the processing to be asynchronous, as intended.

bbum
  • 162,346
  • 23
  • 271
  • 359