Reading all data from serial port, but incoming stream doesn't have a consistent end of stream

StackOverflow https://stackoverflow.com/questions/13832705

  •  07-12-2021
  •  | 
  •  

Question

I'm trying to reverse engineer an old DOS CNC program and I've had limited success. I sniffed the Rx/Tx stream from the DOS program and saw this...

Tx from DOS:

"OUTPUT TEST" 0D 

Rx from machine:

"OUTPUT TEST" 0D 0D 0A 
0D 0A 
"TEST" 0D 0A 
"0001>  +09000  +09000  +00000  +00000  +00000  +00032  +00000  D  O  " 0D 0A 
"0002>  +00000  +03000  +00000  +00000  +00000  +00032  +00000  B  N  " 0D 0A 
"0003>  +00000  +03000  +00000  +00000  +00000  +00032  +00000  B  N  " 0D 0A 
"0004>  +00000  +03000  +00000  +00000  +00000  +00032  +00000  B  N  " 0D 0A 
"0005>  +00000  +03000  +00000  +00000  +00000  +00033  +00000  B  N  " 0D 0A 
"0006>  +00000  +03000  +00000  +00000  +00000  +00033  +00000  B  N  " 0D 0A 
"0007>  +00000  +03000  +00000  +00000  +00000  +00033  +00000  B  N  " 0D 0A 
"0008>  +00000  +03000  +00000  +00000  +00000  +00033  +00000  B  N  " 0D 0A 
"0009>  +00000  +03000  +00000  +00000  +00000  +00033  +00000  B  N  " 0D 0A 
"0010>  +09000  +17000  +00000  +00000  +00000  +00064  +00000  B  X  .  " 0D 0A 
14 0D 0A 
"PIN>  " 

Of course, I had to reformat the stream so it's readable.

As you can see, the last line does not have a line feed. This makes ReadLine useless, as the last line will only show up on the next request. I need to be able to send a command and read to the end. The only way I've been able to achieve this is by sleeping long enough for the transmission to complete on the machine then process the data on the PC. On some machines, the delay has to be set as high as 5 seconds. I'd hate to do it this way, but it works.

While spUISC.BytesToRead > 0
    buffer &= spUISC.ReadExisting
    Threading.Thread.Sleep(100)
End While

Summary

How can I tell if an incoming stream is done if it doesn't have a terminating char?

Was it helpful?

Solution

I personally would modify the loop to do the following:

  1. Read available bytes into the buffer
  2. Attempt to validate that the buffer has a valid response
  3. If yes on #2, consume the buffer and exit the loop. Else keep waiting for more data.

If you can perform a blocking read, there is no need to sleep at all. You'll just keep looping until you get a valid frame. Obviously, other error handling may be required.

OTHER TIPS

Do a blocking read but you'll need to process by character, not line.

"0D 0A PIN> " appears to be a prompt (Process INput?). Don't read until end-of-line, read until you see that prompt (recognize it with a regular expression) and process the bytes preceding the prompt. It appears to be echoing the command characters you send it so after checking discard those characters, leaving a clean response.

To reverse engineer hook up the test box to a terminal program and experiment by hand with commands to that prompt. Commands might be terminated with 0D, 0A or both. E.g. A blank command, "HELP", "?" or an invalid command might give useful information.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top