Почему в ORSSerialPort serialPort: не было ни одного байта NSData для ReReceiveData?

Из моего Arduino я записываю многобайтовые данные в последовательный порт с Serial.print("бла"), но в Objective-C, -serialPort:didReceiveData: (предоставляется ORSSerialPort) получает эти данные только 1 байт за раз. Иногда он захватывает 2 байта одновременно, но никогда не все 4. Это ожидается? Если так, как я могу получить все 4 байта одновременно?

Arduino:

void loop() {
    Serial.print("blah");
    delay(1000);
}

Obj-C:

- (void)serialPort:(ORSSerialPort *)serialPort didReceiveData:(NSData *)data {
   NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
   NSLog(@"%@",string);
}

Установка точки останова внутри этого метода показывает, что data содержит только 1 байт.

1 ответ

Решение

Это нормальное, ожидаемое поведение. Базовое последовательное аппаратное и программное обеспечение не имеет возможности узнать, сколько байтов вы ожидаете или как выглядит полный пакет, поэтому он просто доставляет данные по мере их поступления. Вам нужно будет буферизовать данные в вашем Objective- С кодом. По сути, это довольно просто. Создать NSMutableData что вы можете использовать в качестве буфера:

@property (strong) NSMutableData *incomingDataBuffer;

Инициализируйте его (например, в -init):

_incomingDataBuffer = [[NSMutableData alloc] init];

Тогда в вашем -serialPort:didReceiveData::

- (void)serialPort:(ORSSerialPort *)serialPort didReceiveData:(NSData *)data
{
   [self.incomingDataBuffer appendData:data];

   if ([self dataBufferHasCompletePacket]) { // Check to see if buffer contains a complete, valid packet
       [self processReceivedDataPacket:self.incomingDataBuffer]; // Do whatever you need to do with the received data
       [self.incomingDataBuffer replaceBytesInRange:NSMakeRange(0, [self.incomingDataBuffer length]) withBytes:NULL length:0]; // Clear data buffer
   }
}

Это хорошее начало. У него есть некоторые недостатки, а именно то, что он остановится и никогда не обнаружит, что данные перестали поступать, если, например, по проводному каналу приходит поврежденный пакет, за которым следует допустимый, или последовательный кабель отключен прямо в середине пакета. Эти недостатки могут быть исправлены с помощью комбинации хорошо разработанного формата пакета, включая, например, уникальный заголовок, контрольную сумму и / или конечную последовательность и тайм-ауты, которые заставляют приемник сбросить свое состояние.

Я имел в виду некоторые улучшения для решения этой самой проблемы в самом ORSSerialPort. В этом выпуске обсуждается этот материал на GitHub. Не стесняйтесь добавлять свои комментарии и предложения по этому вопросу, если это то, что вас интересует.

Другие вопросы по тегам