http://www.perlmonks.org?node_id=481318

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

I've got a network device connected to my COM1 (serial) port, which is itself connected to several data collecting devices (barcode readers, etc). when these child devices have data, they send it to this parent network device, which stores the data until MY machine polls it for data (by sending a 'POLL' character, the ASCII ENQ char). if it's polled but has no data to send, it responds with a 'RESET' character (the ASCII EOT char)

I'm using Win32::SerialPort to handle all the dirty stuff, and I just need to receive the data in a stream. I know the network device will always send data in chunks LESS THAN $BUFFER amount of bytes, so I tried to read() or sysread() that many bytes from the serial port, but that seems to block until it gets AT LEAST that many bytes.

I guess i need a way to read UP TO $BUFFER amount of bytes until the stream is empty, then return control.

::takes a breath:: So..can anyone help me figure out WHAT to do and HOW to do it? i greatly appreciate the help :)
#!/usr/bin/perl ## Includes #################################################### # import any modules or pragmas we may need use strict; use Win32::SerialPort qw( :STAT 0.19 ); ## Initialization ############################################## # get everything defined and set up for the main loop, which # will sit on COM1, soliciting (polling) the controller # This hash contains all control character acronyms as hash keys, # with their respective ASCII values as corresponding hash values my %IM = ( 'SOM' => chr(2), #Start of message (STX) 'EOM' => chr(3), #End of message (ETX) 'AFF' => chr(6), #Affirmative Acknowledge (ACK) 'NEG' => chr(21), #Negative Acknowledge (NAK) 'POL' => chr(5), #Poll for data (ENQ) 'SEL' => chr(7), #Alarm (BEL) 'EOR' => chr(13), #End of record (CR) 'DLE' => chr(16), #DLE 'RES' => chr(4), #Reset (EOT) ); # Software-side buffer size, the maximum amount of data that # any single transmission will contain my $BUFFER = 2048; # create object bound to COM port, tie it to filehandle SERIAL, # and load settings from a config file my $PortObj = tie (*SERIAL, 'Win32::SerialPort', "C:\\com.cfg") || die + "Can't open COM1: $^E\n"; # some global variables for stat tracking (not yet implemented) my($upstream,$downstream) = 0; # create a flag variable initialized to zero... my $EXIT = 0; # ...when system signal INTERRUPT is sent, set flag to 1 $SIG{INT} = sub { $EXIT = 1 }; # begin new append to logfile open(LOG,">>C:\\COMDUMP.LOG"); print LOG "\n\nBEGIN: ",time,"\n"; ## Main Loop ################################################### # poll host for data every second, when data is recieved, print # it to STDOUT and a logfile (for now) print "\nPress Ctrl+C to exit\n\n"; my $temp; # main loop, continues until user sends INTERRUPT (ctrl+c) while($EXIT == 0) { $temp = pollForData(); if(defined($temp)) { print $temp; print LOG $temp; } sleep(1); } ## Cleanup ################################################### # close any COM ports, untie any filehandles, undefine objects, # and just tidy up in general before we exit close(LOG); $PortObj->close || die "failed to close"; untie *SERIAL; undef $PortObj; ## Subroutines ################################################# # any repetetive actions that can be reused, we'll store in here # as callable subroutines # polls the controller, retreives, and returns data, or returns # undef if there is no data sub pollForData { my($length,$buffer); # Poll controller to send any pending data (if there is none, # it will send back a 'RES' control character print SERIAL $IM{'POL'}; $upstream++; # read in $BUFFER amount of bytes $length = sysread(SERIAL,$buffer,$BUFFER); # update num of bytes received so far $downstream += $length; # if reset signal sent, there's no data pending, return undef if($buffer eq $IM{'RES'}) return undef; # otherwise, return data return $buffer; }

__________
Give a man a match and he'll be warm for an hour. Set him on fire and he'll be warm for the rest of his life.