Skip to content

Modes of Operation

Will Hedgecock edited this page Jun 30, 2023 · 30 revisions

Although this library was designed to be as simple and flexible as possible, you can enable a number of different modes of operation via manipulation of the serial port timeout values and the interface through which you choose to access the serial port.

The following list indicates the modes of operation possible using this library, as well as a description of what each mode entails and how to enable it:

Note that no matter what mode you choose, if you specify a read timeout and no data is available for reading before that timeout expires, any pending calls to a read() or readBytes() method will throw a SerialPortTimeoutException.

If you simply open a port without specifying any particular mode of operation, it will default to opening in Non-Blocking Mode.


Non-Blocking Mode

In non-blocking mode, a call to any of the read() or readBytes() methods will return immediately with any available data. If no data is available, it will return immediately with a 0 to indicate no data.

To specify this mode of operation, you must call the setComPortTimeouts() method with a timeout mode of TIMEOUT_NONBLOCKING.

Read Semi-Blocking Mode

In this mode, a call to any of the read() or readBytes() methods will block until the number of milliseconds specified by the newReadTimeout parameter has elapsed or at least 1 byte of data can be read.

To specify this mode of operation, you must call the setComPortTimeouts() method with a timeout mode of TIMEOUT_READ_SEMI_BLOCKING.

Read Full-Blocking Mode

In this mode, a call to any of the read() or readBytes() methods will block until the number of milliseconds specified by the newReadTimeout parameter has elapsed or the total number of requested bytes can be read.

To specify this mode of operation, you must call the setComPortTimeouts() method with a timeout mode of TIMEOUT_READ_BLOCKING.

Read Semi-Blocking/Write Full-Blocking Mode

In this mode, a call to any of the read() or readBytes() methods will block until the number of milliseconds specified by the newReadTimeout parameter has elapsed or at least 1 byte of data can be read. A call to any of the write() or writeBytes() methods will block until the number of milliseconds specified by the newWriteTimeout parameter has elapsed or the total number of requested bytes can be written.

To specify this mode of operation, you must call the setComPortTimeouts() method with an OR'd timeout mode of TIMEOUT_READ_SEMI_BLOCKING | TIMEOUT_WRITE_BLOCKING.

Read/Write Full-Blocking Mode

In this mode, a call to any of the read(), readBytes(), write(), or writeBytes() methods will block until the numbers of milliseconds specified by the newReadTimeout or newWriteTimeout parameters have elapsed or the total number of requested bytes can be read or written.

To specify this mode of operation, you must call the setComPortTimeouts() method with an OR'd timeout mode of TIMEOUT_READ_BLOCKING | TIMEOUT_WRITE_BLOCKING.

Event-Driven Callback Mode

In any of the event-driven callback modes, you can register your own custom callback to be triggered upon certain serial I/O events. Your callback can even listen for multiple types of events simultaneously by OR'ing together the various event type flags as described here. Note that all timeout settings are disregarded when the serial port is operating in an event-driven callback mode listening for the LISTENING_EVENT_DATA_RECEIVED event type, and you should never try to mix both event-driven and synchronous port communications at the same time. The events you can listen for are:

For Data Availability

In this case, your callback will be triggered whenever there is any data available to be read over the serial port. Once your callback is triggered, you can optionally call bytesAvailable() to determine how much data is available to read, and you actually read the data using any of the read() or readBytes() methods.

To specify this mode of operation, you simply register a SerialPortDataListener that implements your custom callback using the addDataListener() method. Note that you must override the getListeningEvents() method to return LISTENING_EVENT_DATA_AVAILABLE to enable this mode. Please refer to this usage wiki for an example of how to use this functionality.

For Port Disconnects

In this case, your callback will be triggered whenever it is detected that your serial port has become disconnected, either because the remote device closed the connection or the cable was unplugged. Listening for this event type is highly recommended, so that your application can gracefully handle port disconnects by closing the serial port and either attempting to reconnect or notifying the end user.

To specify this mode of operation, simply register a SerialPortDataListener that implements your custom callback using the addDataListener() method. Note that you must override the getListeningEvents() method to return LISTENING_EVENT_PORT_DISCONNECTED to enable this mode.

For Write Status

In this case, your callback will be triggered whenever all data you have written using any of the write() or writeBytes() methods has actually been transmitted.

Note that this mode of operation is only functional on Windows operating systems due to limitations in Linux's handling of serial writes.

To specify this mode of operation, you simply register a SerialPortDataListener that implements your custom callback using the addDataListener() method. Note that you must override the getListeningEvents() method to return LISTENING_EVENT_DATA_WRITTEN to enable this mode.

For Delimited Packet Reception

In this case, your callback will be triggered whenever one or more delimiter bytes are received on the serial line according to your specification. These delimiter bytes can be used to indicate either the beginning or the end of an expected data packet. This is particularly useful when you are transmitting messages with a known delimiter at the beginning or end of each message.

To specify this mode of operation, you simply register a SerialPortMessageListener that implements your custom callback using the addDataListener() method. Note that in order to enable this mode, you must override the getListeningEvents() method to return LISTENING_EVENT_DATA_RECEIVED, the getMessageDelimiter() method to return the delimiter byte(s) you expect receive to signal the beginning or end of a message and to trigger your callback, and the delimiterIndicatesEndOfMessage() method to indicate whether your delimiter specifies the end or the beginning of a data packet. Please refer to this usage wiki for an example of how to use this functionality.

For Full Packet Data Reception

In this case, your callback will be triggered whenever a set amount of data has been read from the serial port. This raw data will be returned to you within your own callback, so there is no further need to read directly from the serial port.

To specify this mode of operation, you simply register a SerialPortPacketListener that implements your custom callback using the addDataListener() method. Note that in order to enable this mode, you must override both the getListeningEvents() method to return LISTENING_EVENT_DATA_RECEIVED and the getPacketSize() method to return the number of data bytes you expect receive when your callback is triggered. Please refer to this usage wiki for an example of how to use this functionality.

For Control Line Status Changes or Errors

In this case, your callback will be triggered whenever either a modem control line status changes or a communication error has been detected, depending on which specific control lines and/or errors your custom callback is registered to listen for. In almost all cases, this mode of operation should never be used, because underlying differences and lack of support among the various operating systems and device drivers make it unlikely that code listening for these events will behave similarly across different serial devices or OS's.

To specify this mode of operation, you simply register a SerialPortDataListener that implements your custom callback using the addDataListener() method. Note that you must override the getListeningEvents() method to return one or more of the event types OR'd together from the list of possible "Secondary Events" shown on this page.