Well, to be honest - it's doing largely what you've asked it to do. To look for some character (which hasn't been specified, so it's presuming a default of "\n"), and return when that character is found-- but it's also non-blocking, so it will happily return nothing even though something may be coming up soon. It doesn't appear to be missing any data for you, but instead returning it at a different time than you expect.
To quote the perldoc: "The lookfor method is designed to be sampled periodically (polled). Any characters after the match pattern are saved for a subsequent lookfor. Internally, lookfor is implemented using the nonblocking input method when called with no parameter. If called with a count, lookfor calls $PortObj->read(count) which blocks until the read is Complete or a Timeout occurs. The blocking alternative should not be used unless a fault time has been defined using read_interval, read_const_time, and read_char_time."
So, you could do it in a loop:
my $value;
while( ! defined($value) || ! length($value) ) {
$value = $serial->lookfor();
}
(This can, of course, loop forever - see below...)
While the OP is on linux, and thereby using Device::SerialPort, I don't know if yak is using win32 or linux. I've had issues with the reliability of the built-in timeouts in the Win32 API, so I prefer the good-ol-obvious using an alarm within an eval block to do blocking reads, and timeout if you don't get back the data in a reasonable timeframe. Sadly, even the blocking form of read() is unreliable on win32 platforms.
I have no problems whatsoever with the following method on any platform (win32, linux, osx, etc.) that has a good serial port class.
I've modified this slightly to do the same as your 'lookfor()' with a newline as the target, and make it so that it gives up after 15 seconds if it didn't get a line... You can make it timeout at whatever you want..
(Note, not compiled, may have typos g)
my $string = '';
eval {
my $chr;
local $SIG{'ALRM'} = sub { die("TimeOut"); };
# expect a complete string within 15 seconds
alarm( 15 );
while( $chr ne "\n" ) {
# we use a while loop, as the serial object may
# return nothing if the buffer is empty for a
# period of time. wrap entire thing in an alarm
# so we don't wait forever, and can capture a timeout
while( ! defined($chr) || ! length($chr) ) {
$chr = $serial->read(1);
}
$string .= $chr;
}
# disable alarm
alarm(0);
}; # end eval block
# check for error
if( $@ ) {
if( $@ =~ /TimeOut/ ) {
return($string);
}
else {
die($@);
}
}
!c