jerryleo has asked for the wisdom of the Perl Monks concerning the following question:

I'm a newbie for perl programming and serial port coding.
The raw data will be output to serial port every 30 seconds.
I use sysread() to read the raw data through serial port.
Each binary data block has different size.
But all of the data block has the same structure, ASCII Header+Binary data+Enter.
Following is one of binary data blocks' example,
$PASHR,PBN,<PBN structure><Enter> ---------- ------------- ----- ^ ^ ^ | | | ASCII Header Binary Data 0x0D 0x0A
I have tow problems with reading binary data through serial port
1. If the last byte of the binary data is 0x0D,
the logged data will miss a 0x0D character. For example,
raw data
$PASHR,PBN, ... ... , 0x0D 0x0D 0x0A
logged data
$PASHR,PBN, ... ... , 0x0D 0x0A
If the last byte of the binary data isn't 0x0D,
I could log the data block without missing anying.
It sounds like that 0x0D will be ignored under certern sort of conditon
2. sysread(STDIN,$Buff,$BuffLen) returned immediately whenever new data arrived serial port,
but $Buff only hold a few of data not the whole complete data block.
Before I save the data to file, I have to filter and process some messages.
How could I get the whole complete data block?
Any ideas?
Thanks

Edit: g0n - replaced pre tags with code tags

Replies are listed 'Best First'.
Re: Problem with logging binary data through serial port
by ikegami (Patriarch) on Jan 15, 2006 at 18:13 UTC

    If the last byte of the binary data is 0x0D, the logged data will miss a 0x0D character.

    \x0D should not disappear. I suspect you're in Windows, and that you didn't binmode the filehandle from which you are reading. Be sure to use binmode on both the handle from which you are reading and the one to which you are writing.

    sysread returned immediately whenever new data arrived serial port,

    That read and sysread are not guaranteed to return LENGTH bytes is documented. If you need more bytes, just use a loop.

    my $buf = ''; my $offset = 0; DATA: for (;;) { # For each record my $buf = ''; my $offset = 0; my $rec; do { # Until we have a record. my $len = sysread(STDIN, $buf, 1024, $offset); die("Unable to read from XXX: $!\n") if not defined $len; die("Unable to read from XXX: Premature end of file\n") if not $len and $offset; last DATA if not $len; my $pos = index($buf, "\x0D\x0A", $offset); $offset += $len; } while $pos < 0; $rec = substr($buf, 0, $pos+2); $buf = substr($buf, $pos+2); ... process $rec ... }

    Update: Optimized the code slightly.

Re: Problem with logging binary data through serial port
by zentara (Cardinal) on Jan 15, 2006 at 18:04 UTC