Help with system.serial.readUntil

Dear All

Good day

Currently I put a script in gateway startup script to call a few scripts and run different threads in the background. Got the inspiration from Phil’s clientserial.py
(How to listen serial data without interruption)

Now, am trying to use the following command to read continuously from a serial port whereby some sensors will send some NMEA 0183 protocol sentences continuously via RS422 serial port :
system.serial.readUntil(port, chr(36), False, 1000)

So far had been able to read correctly if the sentences are good.

However, i encountered two cases which need advice.

1)In the event that the sensor does not send anything, an exception occurs as such

ERROR:root:java.io.IOException: Delimiter not matched before timeout/EOS.
16:14:12.185 [MainThread] ERROR com.inductiveautomation.factorypmi.application.script.builtin.ClientSystemUtilities$4$1 - <HTML>Error running function from <code>fpmi.system.invokeAsynchronous</code>
com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last):
  File "<event:actionPerformed>", line 190, in serialProcess
	at com.inductiveautomation.ignition.modules.serial.scripting.SerialScriptModule.readUntil(SerialScriptModule.java:402)

Wonder, how could I bypass this error?
Because I wish the program to be able to continue to continuously read from the serial port until something appears or perhaps until x seconds later, if still didnt receive anything, then it will stop reading.

2)In the event that a very long string without $, that is sent from some unknown device or say the sensor is spoilt, the system.serial.readUntil will keep on reading non stop even though after several minutes. It keeps on reading the very long string that is without $, and the program wont execute the next line of the program,

Wonder how is it possible to stop it from reading after some time when it cannot find the delimiter ? Is there an interrupt or use another thread to set a timer or something such that after x seconds later, then it will stop reading since it cannot find the $ ? I am not sure how it can be done.

Greatly appreciate for any kind advises

Thank you

1 Like

You're providing a 1000ms timeout to readUntil(). It should stop reading after 1000 milliseconds. Catch the exception.

FWIW, I haven’t used these techniques on the gateway–there might be a bug, as it is a different module. The background() function in clientserial.py is dependent on client tags. It would have to be reworked a bit to work in the gateway with a folder of memory tags instead. The background() function catches exceptions in the nested callable and restarts it. Consider doing something similar.

1 Like

Dear Phil

Thanks for your kind replies and advises

For the first case(ie when it didnt read anything from the serial port), had managed to catch the exception by using
except IOError

However, this exception shares the same exception as others exception eg when the port is not open, etc.

So wonder how to specifically only catch the exception caused by timeout due to system.serial.readUntil ?
Because it didnt mention anything in the user manual 7.9
https://docs.inductiveautomation.com/display/DOC79/system.serial.readUntil

Because it might be quite dangerous or quite harmful if it is caused by other errors or exception that falls in the same category and if i were to restart it as there might be some situation that would need some user or operator intervention.

Thus it would be wonderful if there is only a specific exception pertaining to this exception for timeout for system.serial.readUntil which i could catch.

Any advise is much appreciated

Dear Phil

Yes by right, for the second case, if it receive something but if it didnt find the delimiter within the timeout period(in this case 1000 ms), then it should timeout.

However when it was executed, it didnt happen and i waited a long time even up to few minutes but still nothing happen, unlike the first case whereby the timeout will come immediately after 1000 ms when nothing is received. I had tested it many many times but it still gives the same behavior.

Hence it is rather strange that it is happening. It should give timeout but unexpectedly it didnt give timeout :slight_frown:

Thus am posting to seek help and advise on this.

Well, that would be a bug. You should contact support to report this. In the meantime, you might want to do short timeout reads (not readUntil) into a buffer and locate the delimiter yourself.

1 Like

Thanks Phil
Noted
Will contact support to report it.

Will try using other methods to read with short timeout and addition script in locating the delimiter on our own, using either
system.serial.readBytes(port, numberOfBytes [, timeout])
or
system.serial.readBytesAsString(port, numberOfBytes [, timeout])

Thank you

1 Like