Why does ORSSerialPort serialPort:didReceiveData NSData only have single byte?

徘徊边缘 提交于 2020-01-05 13:08:42

问题


From my Arduino, I'm writing multi-byte data to serial with Serial.print("blah"), but in Objective-C, -serialPort:didReceiveData: (provided by ORSSerialPort) only gets this data 1 byte at a time. Occasionally, it'll grab 2 bytes at once, but never all 4. Is this expected? If so, how can I make it receive all 4 bytes at once?

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);
}

Setting a breakpoint inside this method shows that data only holds 1 byte.


回答1:


This is normal, expected behavior. The underlying serial hardware and software has no way of knowing how many bytes you're waiting for, or what a complete packet looks like, so it simply delivers data as it comes in. You'll have to buffer the data in your Objective-C code. Fundamentally, this is pretty simple. Create an NSMutableData that you can use as a buffer:

@property (strong) NSMutableData *incomingDataBuffer;

Initialize it (e.g. in -init):

_incomingDataBuffer = [[NSMutableData alloc] init];

Then, in your -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
   }
}

This is a good start. It has some flaws, namely that it will stall and never figure out that data has stopped coming in if e.g. a corrupt packet comes over the wire followed by a valid one, or the serial cable is unplugged right in the middle of a packet. These flaws can be fixed by a combination of a well designed packet format, including for example a unique header, checksum and/or end sequence and timeouts that cause the receiver to reset its state.

I've had in mind some enhancements to address this very issue in ORSSerialPort itself. There's some discussion of this stuff in this issue on GitHub. Feel free to add your comments and suggestions on that issue if this is something you're interested in.



来源:https://stackoverflow.com/questions/21593370/why-does-orsserialport-serialportdidreceivedata-nsdata-only-have-single-byte

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!