Почему в 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. Не стесняйтесь добавлять свои комментарии и предложения по этому вопросу, если это то, что вас интересует.