RishiGupta12 / SerialPundit

Serial port communication in Java - FTDI D2XX, HID API, X/Y modem
GNU Affero General Public License v3.0
125 stars 56 forks source link

Timeout for RX and TX on ISerialIOStream #23

Open xamix opened 7 years ago

xamix commented 7 years ago

Hello, I settled your lib which seem to works (I can transmit and receive in BLOCKING mode) I'm currently on Windows but project will need to work on Linux Desktop and Windows.

I wanted to add timeout for the receive parts, so it seem I need to use NONBLOCKING mode:

_outputStream = (SerialComOutByteStream) _serial.getIOStreamInstance(SerialComManager.OutputStream, _handle, SMODE.NONBLOCKING); _inputStream = (SerialComInByteStream) _serial.getIOStreamInstance(SerialComManager.InputStream, _handle, SMODE.NONBLOCKING);

Now I'm stuck because I cannot find a place where I can set the Timeout for RX parts. I saw the following function:

fineTuneReadBehaviour(long handle, int vmin, int vtime, int rit, int rttm, int rttc)

But I don't know how to use it. What are the parameters values. I need for example 3000ms of read timeout. Also I need to differenciate a timeout exception from an error on the stream (ie: if read function on byteStream return -1 for error on stream, what is returned when it timeout? An exception?).

Any help or answer will be appreciated :-)

Regards.

RishiGupta12 commented 7 years ago
  1. This folder has all examples https://github.com/RishiGupta12/SerialPundit/tree/master/applications For API fineTuneReadBehaviour() example is https://github.com/RishiGupta12/SerialPundit/blob/master/applications/d1-timeout-read-com/src/readtimeout/TimeoutReadCallApp.java

  2. Please read the javadoc for fineTuneReadBehaviour() method. Last 3 parameters are applicable for windows and 1st two are used for linux/mac.

  3. If read returns and no data is read this means timeout occurred otherwise read will not return. If error occurs appropriate exception will be thrown which you need to catch in try-catch block.

xamix commented 7 years ago

Hello, thank you for your answer. I missed the JavaDoc parts, my apologies.

So I came to the Windows doc here: https://msdn.microsoft.com/fr-fr/library/windows/desktop/aa363190(v=vs.85).aspx

And in the Remark parts it say:

Remarks

If an application sets ReadIntervalTimeout and ReadTotalTimeoutMultiplier to MAXDWORD and sets ReadTotalTimeoutConstant to a value greater than zero and less than MAXDWORD, one of the following occurs when the ReadFile function is called: If there are any bytes in the input buffer, ReadFile returns immediately with the bytes in the buffer. If there are no bytes in the input buffer, ReadFile waits until a byte arrives and then returns immediately. If no bytes arrive within the time specified by ReadTotalTimeoutConstant, ReadFile times out.

So it seem that it's what I'm looking for get a simple read timeout. I tried to set the timeout like this (with the two parameters equal to MAXDWORD (0xffffffff)):

_serial.fineTuneReadBehaviour(_handle, 0, 0, 0xffffffff, 0xffffffff, 3000);

But it's not possible since it's a negative number with int parameter type and so the function fire an exception.

I tried with Integer.MAX_VALUE, it seem to work but by reading the documentation, it imply multiplyer depending on number of byte to read which is not what I want...

So is there any solution to use the MAXDWORD in your function?

PS: In your example of function for Windows you says that's it's for 500ms tiemout:

            // Tune read method behaviour (500 milliseconds wait timeout value)
            if(osType == SerialComPlatform.OS_WINDOWS) {
                scm.fineTuneReadBehaviour(handle, 0, 0, 0, 0 , 0);

How is it possible with all parameters to 0?

Regards

RishiGupta12 commented 7 years ago

A quick thought, try this: fineTuneReadBehaviour(_handle, 0, 0, 3000, 0, 0);

Ignore that all 0 code, it was under development. I will update.

xamix commented 7 years ago

I cannot say if this works for the moment but reading the documentation involve that this set the ReadTotalTimeoutMultiplier and so:

ReadTotalTimeoutConstant: A constant used to calculate the total time-out period for read operations, in milliseconds. For each read operation, this value is added to the product of the ReadTotalTimeoutMultiplier member and the requested number of bytes.

So it seem not what I expect.

Also I always have problem to determine if a timeout occur: You say :

If read returns and no data is read this means timeout occurred otherwise read will not return. If error occurs appropriate exception will be thrown which you need to catch in try-catch block.

So what if I read on the _inputStream with:

int res = _inputStream.read(); if (res == -1) throw new EOSException();

If it return -1, End of stream occured, but how to detect timeout on this case? How to know that no byte was read because of timeout and not because the port was closed?

Regards

xamix commented 7 years ago

Another issue appear:

Very often I get the following exception

java.io.IOException: Unknown error occured in native layer !
    at com.serialpundit.serial.SerialComInByteStream.read(SerialComInByteStream.java:287)

This occur only when receiving byte in serial port and the function fineTuneReadBehaviour was previously called on the port.

If I don't call fineTuneReadBehaviour after opening the port, then this error seem to not occur.

Also it seem that on Windows RX timeout is not working since read with a tab never reurn 0.

RishiGupta12 commented 7 years ago

There are two goals. One timed read and second port close. Configure finetuneread as mentioned and use non blocking mode when creating stream. This will address goal one. For second goal you will need hardware and driver support. So first we close item one then move to item two.

xamix commented 7 years ago

Hi!

The timeout with fineTuneReadBehaviour on Linux is working, but on Windows it seem to not works properly, I tryed with many parameters:

fineTuneReadBehaviour(_handle, 0, 0, 3000, 0, 0); or fineTuneReadBehaviour(_handle, 0, 0, 0, 0, 3000); ... without any success. The time seem to be about 1second instead of my 3seconds.

RishiGupta12 commented 7 years ago
RishiGupta12 commented 7 years ago

I have also updated example application for timed read TimeoutReadCallApp.java May you please run this example and share results.