I'm not sure I understand your script, but let me see if I at least understand your task. What follows is actually a different plan from what you seem to be trying to do in the OP code, but (if I understand what you said about your sample data strings) I think it might be a useful approach (and might be easier to implement, relative to what you've tried so far):
- You want to read bytes continuously from a serial port
- Every time you receive STX (0x02), you want start capturing/storing input
- Having started capture/storage, you want to stop it when you receive ETX (0x03) and do something with the stored byte sequence, clear the capture buffer, and return to step 2.
- But if you get NAK (0x15) or if more than 79 (80?) bytes get stored before receiving ETX, you want to ditch the capture buffer without further ado and return to step 2.
- Something you didn't mention (but should be considered): if a second STX arrives before an ETX, NAK or 80 bytes have appeared, you should either treat this 2nd STX as data, or else ditch the capture buffer and start a fresh capture.
In other words, a simple 2-state machine would do what you want. The initial state stores nothing and just watches for STX. Once STX is found, you switch to storing input and looking for ETX. You'll stop storing when either ETX or NAK is found or when 80 bytes are stored, whichever comes first, and return to the initial state; if ETX was found first, you'll do something with the stored data, otherwise you'll ditch it.
If that isn't what you meant to describe, please try again to see if you can explain the task more clearly. If that is what you meant, then that description should lead you to a fairly simple script, along the lines of:
my $capture_state = 0; # looking for STX
my @buffer;
while (1) {
$byte = $port->read(1);
if ( $byte == 0x02 ) { # got STX
$capture_state = 1;
@buffer = (); # (if we were already capturing for a prev STX,
+ ditch that)
}
if ( $capture_state ) {
if ( $byte == 0x15 or @buffer > 79 ) { # got NAK or too many
+bytes
@buffer = ();
$capture_state = 0;
}
else {
push @buffer, $byte;
if ( $byte == 0x03 ) { # got ETX
printf "Received complete message of %d bytes:", scala
+r @buffer;
printf " %02x" for ( @buffer );
print "\n";
@buffer = ();
$capture_state = 0;
}
}
}
}
If you want a 2nd STX in the input to be treated as data, just comment out the
@buffer = (); line in the first "if" clause.
(update: made a minor fix to the 2nd "printf" format, to put a space between consecutive byte values)