![JAR search and dependency download from the Maven repository](/logo.png)
jssc.SerialPort Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of test-jssc Show documentation
Show all versions of test-jssc Show documentation
A small, single Java library for working with serial ports across various systems
based on the work from scream3r/java-simple-serial-connector.
The newest version!
/* jSSC (Java Simple Serial Connector) - serial port communication library.
* © Alexey Sokolov (scream3r), 2010-2014.
*
* This file is part of jSSC.
*
* jSSC is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* jSSC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with jSSC. If not, see .
*
* If you use jSSC in public project you can inform me about this by e-mail,
* of course if you want it.
*
* e-mail: [email protected]
* web-site: http://scream3r.org | http://code.google.com/p/java-simple-serial-connector/
*/
package jssc;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
/**
*
* @author scream3r
*/
public class SerialPort {
private SerialNativeInterface serialInterface;
private SerialPortEventListener eventListener;
private long portHandle;
private String portName;
private boolean portOpened = false;
private boolean maskAssigned = false;
private boolean eventListenerAdded = false;
//since 2.2.0 ->
private Method methodErrorOccurred = null;
//<- since 2.2.0
public static final int BAUDRATE_110 = 110;
public static final int BAUDRATE_300 = 300;
public static final int BAUDRATE_600 = 600;
public static final int BAUDRATE_1200 = 1200;
public static final int BAUDRATE_2400 = 2400;
public static final int BAUDRATE_4800 = 4800;
public static final int BAUDRATE_9600 = 9600;
public static final int BAUDRATE_14400 = 14400;
public static final int BAUDRATE_19200 = 19200;
public static final int BAUDRATE_38400 = 38400;
public static final int BAUDRATE_57600 = 57600;
public static final int BAUDRATE_115200 = 115200;
public static final int BAUDRATE_128000 = 128000;
public static final int BAUDRATE_256000 = 256000;
public static final int DATABITS_5 = 5;
public static final int DATABITS_6 = 6;
public static final int DATABITS_7 = 7;
public static final int DATABITS_8 = 8;
public static final int STOPBITS_1 = 1;
public static final int STOPBITS_2 = 2;
public static final int STOPBITS_1_5 = 3;
public static final int PARITY_NONE = 0;
public static final int PARITY_ODD = 1;
public static final int PARITY_EVEN = 2;
public static final int PARITY_MARK = 3;
public static final int PARITY_SPACE = 4;
public static final int PURGE_RXABORT = 0x0002;
public static final int PURGE_RXCLEAR = 0x0008;
public static final int PURGE_TXABORT = 0x0001;
public static final int PURGE_TXCLEAR = 0x0004;
public static final int MASK_RXCHAR = 1;
public static final int MASK_RXFLAG = 2;
public static final int MASK_TXEMPTY = 4;
public static final int MASK_CTS = 8;
public static final int MASK_DSR = 16;
public static final int MASK_RLSD = 32;
public static final int MASK_BREAK = 64;
public static final int MASK_ERR = 128;
public static final int MASK_RING = 256;
//since 0.8 ->
public static final int FLOWCONTROL_NONE = 0;
public static final int FLOWCONTROL_RTSCTS_IN = 1;
public static final int FLOWCONTROL_RTSCTS_OUT = 2;
public static final int FLOWCONTROL_XONXOFF_IN = 4;
public static final int FLOWCONTROL_XONXOFF_OUT = 8;
//<- since 0.8
//since 0.8 ->
public static final int ERROR_FRAME = 0x0008;
public static final int ERROR_OVERRUN = 0x0002;
public static final int ERROR_PARITY = 0x0004;
//<- since 0.8
//since 2.6.0 ->
private static final int PARAMS_FLAG_IGNPAR = 1;
private static final int PARAMS_FLAG_PARMRK = 2;
//<- since 2.6.0
public SerialPort(String portName) {
this.portName = portName;
serialInterface = new SerialNativeInterface();
}
/**
* Getting port name under operation
*
* @return Method returns port name under operation as a String
*/
public String getPortName(){
return portName;
}
/**
* Getting port state
*
* @return Method returns true if port is open, otherwise false
*/
public boolean isOpened() {
return portOpened;
}
/**
* Port opening
*
* Note: If port busy TYPE_PORT_BUSY exception will be thrown.
* If port not found TYPE_PORT_NOT_FOUND exception will be thrown.
*
* @return If the operation is successfully completed, the method returns true
*
* @throws SerialPortException
*/
public boolean openPort() throws SerialPortException {
if(portOpened){
throw new SerialPortException(this, "openPort()", SerialPortException.TYPE_PORT_ALREADY_OPENED);
}
if(portName != null){
boolean useTIOCEXCL = (System.getProperty(SerialNativeInterface.PROPERTY_JSSC_NO_TIOCEXCL) == null &&
System.getProperty(SerialNativeInterface.PROPERTY_JSSC_NO_TIOCEXCL.toLowerCase()) == null);
portHandle = serialInterface.openPort(portName, useTIOCEXCL);//since 2.3.0 -> (if JSSC_NO_TIOCEXCL defined, exclusive lock for serial port will be disabled)
}
else {
throw new SerialPortException(this, "openPort()", SerialPortException.TYPE_NULL_NOT_PERMITTED);//since 2.1.0 -> NULL port name fix
}
if(portHandle == SerialNativeInterface.ERR_PORT_BUSY){
throw new SerialPortException(this, "openPort()", SerialPortException.TYPE_PORT_BUSY);
}
else if(portHandle == SerialNativeInterface.ERR_PORT_NOT_FOUND){
throw new SerialPortException(this, "openPort()", SerialPortException.TYPE_PORT_NOT_FOUND);
}
else if(portHandle == SerialNativeInterface.ERR_PERMISSION_DENIED){
throw new SerialPortException(this, "openPort()", SerialPortException.TYPE_PERMISSION_DENIED);
}
else if(portHandle == SerialNativeInterface.ERR_INCORRECT_SERIAL_PORT){
throw new SerialPortException(this, "openPort()", SerialPortException.TYPE_INCORRECT_SERIAL_PORT);
}
portOpened = true;
return true;
}
/**
* Setting the parameters of port. RTS and DTR lines are enabled by default
*
* @param baudRate data transfer rate
* @param dataBits number of data bits
* @param stopBits number of stop bits
* @param parity parity
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean setParams(int baudRate, int dataBits, int stopBits, int parity) throws SerialPortException {
return setParams(baudRate, dataBits, stopBits, parity, true, true);
}
/**
* Setting the parameters of port
*
* @param baudRate data transfer rate
* @param dataBits number of data bits
* @param stopBits number of stop bits
* @param parity parity
* @param setRTS initial state of RTS line(ON/OFF)
* @param setDTR initial state of DTR line(ON/OFF)
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*
* @since 0.8
*/
public boolean setParams(int baudRate, int dataBits, int stopBits, int parity, boolean setRTS, boolean setDTR) throws SerialPortException {
checkPortOpened("setParams()");
if(stopBits == 1){
stopBits = 0;
}
else if(stopBits == 3){
stopBits = 1;
}
int flags = 0;
if(System.getProperty(SerialNativeInterface.PROPERTY_JSSC_IGNPAR) != null || System.getProperty(SerialNativeInterface.PROPERTY_JSSC_IGNPAR.toLowerCase()) != null){
flags |= PARAMS_FLAG_IGNPAR;
}
if(System.getProperty(SerialNativeInterface.PROPERTY_JSSC_PARMRK) != null || System.getProperty(SerialNativeInterface.PROPERTY_JSSC_PARMRK.toLowerCase()) != null){
flags |= PARAMS_FLAG_PARMRK;
}
return serialInterface.setParams(portHandle, baudRate, dataBits, stopBits, parity, setRTS, setDTR, flags);
}
/**
* Purge of input and output buffer. Required flags shall be sent to the input. Variables with prefix
* "PURGE_", for example "PURGE_RXCLEAR". Sent parameter "flags" is additive value,
* so addition of flags is allowed. For example, if input or output buffer shall be purged,
* parameter "PURGE_RXCLEAR | PURGE_TXCLEAR".
*
Note: some devices or drivers may not support this function
*
* @return If the operation is successfully completed, the method returns true, otherwise false.
*
* @throws SerialPortException
*/
public boolean purgePort(int flags) throws SerialPortException {
checkPortOpened("purgePort()");
return serialInterface.purgePort(portHandle, flags);
}
/**
* Events mask for Linux OS
*
* @since 0.8
*/
private int linuxMask;
/**
* Set events mask. Required flags shall be sent to the input. Variables with prefix
* "MASK_", shall be used as flags, for example "MASK_RXCHAR".
* Sent parameter "mask" is additive value, so addition of flags is allowed.
* For example if messages about data receipt and CTS and DSR status changing
* shall be received, it is required to set the mask - "MASK_RXCHAR | MASK_CTS | MASK_DSR"
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean setEventsMask(int mask) throws SerialPortException {
checkPortOpened("setEventsMask()");
if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_LINUX ||
SerialNativeInterface.getOsType() == SerialNativeInterface.OS_SOLARIS ||
SerialNativeInterface.getOsType() == SerialNativeInterface.OS_MAC_OS_X){//since 0.9.0
linuxMask = mask;
if(mask > 0){
maskAssigned = true;
}
else {
maskAssigned = false;
}
return true;
}
boolean returnValue = serialInterface.setEventsMask(portHandle, mask);
if(!returnValue){
throw new SerialPortException(this, "setEventsMask()", SerialPortException.TYPE_CANT_SET_MASK);
}
if(mask > 0){
maskAssigned = true;
}
else {
maskAssigned = false;
}
return returnValue;
}
/**
* Getting events mask for the port
*
* @return Method returns events mask as int type variable. This variable is an additive value
*
* @throws SerialPortException
*/
public int getEventsMask() throws SerialPortException {
checkPortOpened("getEventsMask()");
if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_LINUX ||
SerialNativeInterface.getOsType() == SerialNativeInterface.OS_SOLARIS ||
SerialNativeInterface.getOsType() == SerialNativeInterface.OS_MAC_OS_X){//since 0.9.0
return linuxMask;
}
return serialInterface.getEventsMask(portHandle);
}
/**
* Getting events mask for the port is Linux OS (for internal use)
*
* @since 0.8
*/
private int getLinuxMask() {
return linuxMask;
}
/**
* Change RTS line state. Set "true" for switching ON and "false" for switching OFF RTS line
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean setRTS(boolean enabled) throws SerialPortException {
checkPortOpened("setRTS()");
return serialInterface.setRTS(portHandle, enabled);
}
/**
* Change DTR line state. Set "true" for switching ON and "false" for switching OFF DTR line
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean setDTR(boolean enabled) throws SerialPortException {
checkPortOpened("setDTR()");
return serialInterface.setDTR(portHandle, enabled);
}
/**
* Write byte array to port
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean writeBytes(byte[] buffer) throws SerialPortException {
checkPortOpened("writeBytes()");
return serialInterface.writeBytes(portHandle, buffer);
}
/**
* Write single byte to port
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*
* @since 0.8
*/
public boolean writeByte(byte singleByte) throws SerialPortException {
checkPortOpened("writeByte()");
return writeBytes(new byte[]{singleByte});
}
/**
* Write String to port
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*
* @since 0.8
*/
public boolean writeString(String string) throws SerialPortException {
checkPortOpened("writeString()");
return writeBytes(string.getBytes());
}
/**
* Write String to port
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*
* @since 2.8.0
*/
public boolean writeString(String string, String charsetName) throws SerialPortException, UnsupportedEncodingException {
checkPortOpened("writeString()");
return writeBytes(string.getBytes(charsetName));
}
/**
* Write int value (in range from 0 to 255 (0x00 - 0xFF)) to port
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*
* @since 0.8
*/
public boolean writeInt(int singleInt) throws SerialPortException {
checkPortOpened("writeInt()");
return writeBytes(new byte[]{(byte)singleInt});
}
/**
* Write int array (in range from 0 to 255 (0x00 - 0xFF)) to port
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*
* @since 0.8
*/
public boolean writeIntArray(int[] buffer) throws SerialPortException {
checkPortOpened("writeIntArray()");
byte[] byteArray = new byte[buffer.length];
for(int i = 0; i < buffer.length; i++){
byteArray[i] = (byte)buffer[i];
}
return writeBytes(byteArray);
}
/**
* Read byte array from port
*
* @param byteCount count of bytes for reading
*
* @return byte array with "byteCount" length
*
* @throws SerialPortException
*/
public byte[] readBytes(int byteCount) throws SerialPortException {
checkPortOpened("readBytes()");
return serialInterface.readBytes(portHandle, byteCount);
}
/**
* Read string from port
*
* @param byteCount count of bytes for reading
*
* @return byte array with "byteCount" length converted to String
*
* @throws SerialPortException
*
* @since 0.8
*/
public String readString(int byteCount) throws SerialPortException {
checkPortOpened("readString()");
return new String(readBytes(byteCount));
}
/**
* Read Hex string from port (example: FF 0A FF). Separator by default is a space
*
* @param byteCount count of bytes for reading
*
* @return byte array with "byteCount" length converted to Hexadecimal String
*
* @throws SerialPortException
*
* @since 0.8
*/
public String readHexString(int byteCount) throws SerialPortException {
checkPortOpened("readHexString()");
return readHexString(byteCount, " ");
}
/**
* Read Hex string from port with setted separator (example if separator is "::": FF::0A::FF)
*
* @param byteCount count of bytes for reading
*
* @return byte array with "byteCount" length converted to Hexadecimal String
*
* @throws SerialPortException
*
* @since 0.8
*/
public String readHexString(int byteCount, String separator) throws SerialPortException {
checkPortOpened("readHexString()");
String[] strBuffer = readHexStringArray(byteCount);
StringBuilder returnString = new StringBuilder();
boolean insertSeparator = false;
for(String value : strBuffer){
if(insertSeparator){
returnString.append(separator);
}
returnString.append(value);
insertSeparator = true;
}
return returnString.toString();
}
/**
* Read Hex String array from port
*
* @param byteCount count of bytes for reading
*
* @return String array with "byteCount" length and Hexadecimal String values
*
* @throws SerialPortException
*
* @since 0.8
*/
public String[] readHexStringArray(int byteCount) throws SerialPortException {
checkPortOpened("readHexStringArray()");
int[] intBuffer = readIntArray(byteCount);
String[] strBuffer = new String[intBuffer.length];
for(int i = 0; i < intBuffer.length; i++){
String value = Integer.toHexString(intBuffer[i]).toUpperCase();
if(value.length() == 1) {
value = "0" + value;
}
strBuffer[i] = value;
}
return strBuffer;
}
/**
* Read int array from port
*
* @param byteCount count of bytes for reading
*
* @return int array with values in range from 0 to 255
*
* @throws SerialPortException
*
* @since 0.8
*/
public int[] readIntArray(int byteCount) throws SerialPortException {
checkPortOpened("readIntArray()");
byte[] buffer = readBytes(byteCount);
int[] intBuffer = new int[buffer.length];
for(int i = 0; i < buffer.length; i++){
if(buffer[i] < 0){
intBuffer[i] = 256 + buffer[i];
}
else {
intBuffer[i] = buffer[i];
}
}
return intBuffer;
}
private void waitBytesWithTimeout(String methodName, int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
checkPortOpened("waitBytesWithTimeout()");
boolean timeIsOut = true;
long startTime = System.currentTimeMillis();
while((System.currentTimeMillis() - startTime) < timeout){
if(getInputBufferBytesCount() >= byteCount){
timeIsOut = false;
break;
}
try {
Thread.sleep(0, 100);//Need to sleep some time to prevent high CPU loading
}
catch (InterruptedException ex) {
//Do nothing
}
}
if(timeIsOut){
throw new SerialPortTimeoutException(portName, methodName, timeout);
}
}
/**
* Read byte array from port
*
* @param byteCount count of bytes for reading
* @param timeout timeout in milliseconds
*
* @return byte array with "byteCount" length
*
* @throws SerialPortException
* @throws SerialPortTimeoutException
*
* @since 2.0
*/
public byte[] readBytes(int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
checkPortOpened("readBytes()");
waitBytesWithTimeout("readBytes()", byteCount, timeout);
return readBytes(byteCount);
}
/**
* Read string from port
*
* @param byteCount count of bytes for reading
* @param timeout timeout in milliseconds
*
* @return byte array with "byteCount" length converted to String
*
* @throws SerialPortException
* @throws SerialPortTimeoutException
*
* @since 2.0
*/
public String readString(int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
checkPortOpened("readString()");
waitBytesWithTimeout("readString()", byteCount, timeout);
return readString(byteCount);
}
/**
* Read Hex string from port (example: FF 0A FF). Separator by default is a space
*
* @param byteCount count of bytes for reading
* @param timeout timeout in milliseconds
*
* @return byte array with "byteCount" length converted to Hexadecimal String
*
* @throws SerialPortException
* @throws SerialPortTimeoutException
*
* @since 2.0
*/
public String readHexString(int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
checkPortOpened("readHexString()");
waitBytesWithTimeout("readHexString()", byteCount, timeout);
return readHexString(byteCount);
}
/**
* Read Hex string from port with setted separator (example if separator is "::": FF::0A::FF)
*
* @param byteCount count of bytes for reading
* @param timeout timeout in milliseconds
*
* @return byte array with "byteCount" length converted to Hexadecimal String
*
* @throws SerialPortException
* @throws SerialPortTimeoutException
*
* @since 2.0
*/
public String readHexString(int byteCount, String separator, int timeout) throws SerialPortException, SerialPortTimeoutException {
checkPortOpened("readHexString()");
waitBytesWithTimeout("readHexString()", byteCount, timeout);
return readHexString(byteCount, separator);
}
/**
* Read Hex String array from port
*
* @param byteCount count of bytes for reading
* @param timeout timeout in milliseconds
*
* @return String array with "byteCount" length and Hexadecimal String values
*
* @throws SerialPortException
* @throws SerialPortTimeoutException
*
* @since 2.0
*/
public String[] readHexStringArray(int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
checkPortOpened("readHexStringArray()");
waitBytesWithTimeout("readHexStringArray()", byteCount, timeout);
return readHexStringArray(byteCount);
}
/**
* Read int array from port
*
* @param byteCount count of bytes for reading
* @param timeout timeout in milliseconds
*
* @return int array with values in range from 0 to 255
*
* @throws SerialPortException
* @throws SerialPortTimeoutException
*
* @since 2.0
*/
public int[] readIntArray(int byteCount, int timeout) throws SerialPortException, SerialPortTimeoutException {
checkPortOpened("readIntArray()");
waitBytesWithTimeout("readIntArray()", byteCount, timeout);
return readIntArray(byteCount);
}
/**
* Read all available bytes from port like a byte array
*
* @return If input buffer is empty null will be returned, else byte array with all data from port
*
* @throws SerialPortException
*
* @since 0.8
*/
public byte[] readBytes() throws SerialPortException {
checkPortOpened("readBytes()");
int byteCount = getInputBufferBytesCount();
if(byteCount <= 0){
return null;
}
return readBytes(byteCount);
}
/**
* Read all available bytes from port like a String
*
* @return If input buffer is empty null will be returned, else byte array with all data from port converted to String
*
* @throws SerialPortException
*
* @since 0.8
*/
public String readString() throws SerialPortException {
checkPortOpened("readString()");
int byteCount = getInputBufferBytesCount();
if(byteCount <= 0){
return null;
}
return readString(byteCount);
}
/**
* Read all available bytes from port like a Hex String
*
* @return If input buffer is empty null will be returned, else byte array with all data from port converted to Hex String
*
* @throws SerialPortException
*
* @since 0.8
*/
public String readHexString() throws SerialPortException {
checkPortOpened("readHexString()");
int byteCount = getInputBufferBytesCount();
if(byteCount <= 0){
return null;
}
return readHexString(byteCount);
}
/**
* Read all available bytes from port like a Hex String with setted separator
*
* @return If input buffer is empty null will be returned, else byte array with all data from port converted to Hex String
*
* @throws SerialPortException
*
* @since 0.8
*/
public String readHexString(String separator) throws SerialPortException {
checkPortOpened("readHexString()");
int byteCount = getInputBufferBytesCount();
if(byteCount <= 0){
return null;
}
return readHexString(byteCount, separator);
}
/**
* Read all available bytes from port like a Hex String array
*
* @return If input buffer is empty null will be returned, else byte array with all data from port converted to Hex String array
*
* @throws SerialPortException
*
* @since 0.8
*/
public String[] readHexStringArray() throws SerialPortException {
checkPortOpened("readHexStringArray()");
int byteCount = getInputBufferBytesCount();
if(byteCount <= 0){
return null;
}
return readHexStringArray(byteCount);
}
/**
* Read all available bytes from port like a int array (values in range from 0 to 255)
*
* @return If input buffer is empty null will be returned, else byte array with all data from port converted to int array
*
* @throws SerialPortException
*
* @since 0.8
*/
public int[] readIntArray() throws SerialPortException {
checkPortOpened("readIntArray()");
int byteCount = getInputBufferBytesCount();
if(byteCount <= 0){
return null;
}
return readIntArray(byteCount);
}
/**
* Get count of bytes in input buffer
*
* @return Count of bytes in input buffer or -1 if error occured
*
* @throws SerialPortException
*
* @since 0.8
*/
public int getInputBufferBytesCount() throws SerialPortException {
checkPortOpened("getInputBufferBytesCount()");
return serialInterface.getBuffersBytesCount(portHandle)[0];
}
/**
* Get count of bytes in output buffer
*
* @return Count of bytes in output buffer or -1 if error occured
*
* @throws SerialPortException
*
* @since 0.8
*/
public int getOutputBufferBytesCount() throws SerialPortException {
checkPortOpened("getOutputBufferBytesCount()");
return serialInterface.getBuffersBytesCount(portHandle)[1];
}
/**
* Set flow control mode. For required mode use variables with prefix "FLOWCONTROL_".
* Example of hardware flow control mode(RTS/CTS): setFlowControlMode(FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT);
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*
* @since 0.8
*/
public boolean setFlowControlMode(int mask) throws SerialPortException {
checkPortOpened("setFlowControlMode()");
return serialInterface.setFlowControlMode(portHandle, mask);
}
/**
* Get flow control mode
*
* @return Mask of setted flow control mode
*
* @throws SerialPortException
*
* @since 0.8
*/
public int getFlowControlMode() throws SerialPortException {
checkPortOpened("getFlowControlMode()");
return serialInterface.getFlowControlMode(portHandle);
}
/**
* Send Break singnal for setted duration
*
* @param duration duration of Break signal
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*
* @since 0.8
*/
public boolean sendBreak(int duration)throws SerialPortException {
checkPortOpened("sendBreak()");
return serialInterface.sendBreak(portHandle, duration);
}
private int[][] waitEvents() {
return serialInterface.waitEvents(portHandle);
}
/**
* Check port opened (since jSSC-0.8 String "EMPTY" was replaced with "portName" variable)
*
* @param methodName method name
*
* @throws SerialPortException
*/
private void checkPortOpened(String methodName) throws SerialPortException {
if(!portOpened){
throw new SerialPortException(this, methodName, SerialPortException.TYPE_PORT_NOT_OPENED);
}
}
/**
* Getting lines status. Lines status is sent as 0 – OFF and 1 - ON
*
* @return Method returns the array containing information about lines in following order:
*
element 0 - CTS line state
*
element 1 - DSR line state
*
element 2 - RING line state
*
element 3 - RLSD line state
*
* @throws SerialPortException
*/
public int[] getLinesStatus() throws SerialPortException {
checkPortOpened("getLinesStatus()");
return serialInterface.getLinesStatus(portHandle);
}
/**
* Get state of CTS line
*
* @return If line is active, method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean isCTS() throws SerialPortException {
checkPortOpened("isCTS()");
if(serialInterface.getLinesStatus(portHandle)[0] == 1){
return true;
}
else {
return false;
}
}
/**
* Get state of DSR line
*
* @return If line is active, method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean isDSR() throws SerialPortException {
checkPortOpened("isDSR()");
if(serialInterface.getLinesStatus(portHandle)[1] == 1){
return true;
}
else {
return false;
}
}
/**
* Get state of RING line
*
* @return If line is active, method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean isRING() throws SerialPortException {
checkPortOpened("isRING()");
if(serialInterface.getLinesStatus(portHandle)[2] == 1){
return true;
}
else {
return false;
}
}
/**
* Get state of RLSD line
*
* @return If line is active, method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean isRLSD() throws SerialPortException {
checkPortOpened("isRLSD()");
if(serialInterface.getLinesStatus(portHandle)[3] == 1){
return true;
}
else {
return false;
}
}
/**
* Add event listener. Object of "SerialPortEventListener" type shall
* be sent to the method. This object shall be properly described, as it will
* be in charge for handling of occurred events. This method will independently
* set the mask in "MASK_RXCHAR" state if it was not set beforehand
*
* @throws SerialPortException
*/
public void addEventListener(SerialPortEventListener listener) throws SerialPortException {
addEventListener(listener, MASK_RXCHAR, false);
}
/**
* Add event listener. Object of "SerialPortEventListener" type shall be sent
* to the method. This object shall be properly described, as it will be in
* charge for handling of occurred events. Also events mask shall be sent to
* this method, to do it use variables with prefix "MASK_" for example "MASK_RXCHAR"
*
* @see #setEventsMask(int) setEventsMask(int mask)
*
* @throws SerialPortException
*/
public void addEventListener(SerialPortEventListener listener, int mask) throws SerialPortException {
addEventListener(listener, mask, true);
}
/**
* Internal method. Add event listener. Object of "SerialPortEventListener" type shall be sent
* to the method. This object shall be properly described, as it will be in
* charge for handling of occurred events. Also events mask shall be sent to
* this method, to do it use variables with prefix "MASK_" for example "MASK_RXCHAR". If
* overwriteMask == true and mask has been already assigned it value will be rewrited by mask
* value, if overwriteMask == false and mask has been already assigned the new mask value will be ignored,
* if there is no assigned mask to this serial port the mask value will be used for setting it up in spite of
* overwriteMask value
*
* @see #setEventsMask(int) setEventsMask(int mask)
*
* @throws SerialPortException
*/
private void addEventListener(SerialPortEventListener listener, int mask, boolean overwriteMask) throws SerialPortException {
checkPortOpened("addEventListener()");
if(!eventListenerAdded){
if((maskAssigned && overwriteMask) || !maskAssigned) {
setEventsMask(mask);
}
eventListener = listener;
eventThread = getNewEventThread();
eventThread.setName("EventThread " + portName);
//since 2.2.0 ->
try {
Method method = eventListener.getClass().getMethod("errorOccurred", new Class>[]{SerialPortException.class});
method.setAccessible(true);
methodErrorOccurred = method;
}
catch (SecurityException ex) {
//Do nothing
}
catch (NoSuchMethodException ex) {
//Do nothing
}
//<- since 2.2.0
eventThread.start();
eventListenerAdded = true;
}
else {
throw new SerialPortException(this, "addEventListener()", SerialPortException.TYPE_LISTENER_ALREADY_ADDED);
}
}
/**
* Create new EventListener Thread depending on the type of operating system
*
* @since 0.8
*/
private EventThread getNewEventThread() {
if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_LINUX ||
SerialNativeInterface.getOsType() == SerialNativeInterface.OS_SOLARIS ||
SerialNativeInterface.getOsType() == SerialNativeInterface.OS_MAC_OS_X){//since 0.9.0
return new LinuxEventThread();
}
return new EventThread();
}
/**
* Delete event listener. Mask is set to 0. So at the next addition of event
* handler you shall set required event mask again
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean removeEventListener() throws SerialPortException {
checkPortOpened("removeEventListener()");
if(!eventListenerAdded){
throw new SerialPortException(this, "removeEventListener()", SerialPortException.TYPE_CANT_REMOVE_LISTENER);
}
eventThread.terminateThread();
setEventsMask(0);
if(Thread.currentThread().getId() != eventThread.getId()){
if(eventThread.isAlive()){
try {
eventThread.join(5000);
}
catch (InterruptedException ex) {
throw new SerialPortException(this, "removeEventListener()", SerialPortException.TYPE_LISTENER_THREAD_INTERRUPTED);
}
}
}
methodErrorOccurred = null;
eventListenerAdded = false;
return true;
}
/**
* Close port. This method deletes event listener first, then closes the port
*
* @return If the operation is successfully completed, the method returns true, otherwise false
*
* @throws SerialPortException
*/
public boolean closePort() throws SerialPortException {
checkPortOpened("closePort()");
if(eventListenerAdded){
removeEventListener();
}
boolean returnValue = serialInterface.closePort(portHandle);
if(returnValue){
maskAssigned = false;
portOpened = false;
}
return returnValue;
}
private EventThread eventThread;
private class EventThread extends Thread {
private boolean threadTerminated = false;
@Override
public void run() {
while(!threadTerminated){
int[][] eventArray = waitEvents();
for(int[] event : eventArray){
if(event[0] > 0 && !threadTerminated){
eventListener.serialEvent(new SerialPortEvent(SerialPort.this, event[0], event[1]));
//FIXME
/*if(methodErrorOccurred != null){
try {
methodErrorOccurred.invoke(eventListener, new Object[]{new SerialPortException(SerialPort.this, "method", "exception")});
}
catch (Exception ex) {
System.out.println(ex);
}
}*/
}
}
}
}
private void terminateThread(){
threadTerminated = true;
}
}
/**
* EventListener for Linux OS
*
* @since 0.8
*/
private class LinuxEventThread extends EventThread {
//Essential interruptions for events: BREAK, ERR, TXEMPTY
private final int INTERRUPT_BREAK = 512;
private final int INTERRUPT_TX = 1024;
private final int INTERRUPT_FRAME = 2048;
private final int INTERRUPT_OVERRUN = 4096;
private final int INTERRUPT_PARITY = 8192;
//Count of interruptions
private int interruptBreak;
private int interruptTX;
private int interruptFrame;
private int interruptOverrun;
private int interruptParity;
//Previous states if lines (then state change event will be generated)
private int preCTS;
private int preDSR;
private int preRLSD;
private int preRING;
//Need to get initial states
public LinuxEventThread(){
int[][] eventArray = waitEvents();
for(int[] event : eventArray){
int eventType = event[0];
int eventValue = event[1];
switch(eventType){
case INTERRUPT_BREAK:
interruptBreak = eventValue;
break;
case INTERRUPT_TX:
interruptTX = eventValue;
break;
case INTERRUPT_FRAME:
interruptFrame = eventValue;
break;
case INTERRUPT_OVERRUN:
interruptOverrun = eventValue;
break;
case INTERRUPT_PARITY:
interruptParity = eventValue;
break;
case MASK_CTS:
preCTS = eventValue;
break;
case MASK_DSR:
preDSR = eventValue;
break;
case MASK_RING:
preRING = eventValue;
break;
case MASK_RLSD:
preRLSD = eventValue;
break;
}
}
}
@Override
public void run() {
while(!super.threadTerminated){
int[][] eventArray = waitEvents();
int mask = getLinuxMask();
boolean interruptTxChanged = false;
int errorMask = 0;
for(int[] event : eventArray){
boolean sendEvent = false;
int eventType = event[0];
int eventValue = event[1];
if(eventType > 0 && !super.threadTerminated){
switch(eventType){
case INTERRUPT_BREAK:
if(eventValue != interruptBreak){
interruptBreak = eventValue;
if((mask & MASK_BREAK) == MASK_BREAK){
eventType = MASK_BREAK;
eventValue = 0;
sendEvent = true;
}
}
break;
case INTERRUPT_TX:
if(eventValue != interruptTX){
interruptTX = eventValue;
interruptTxChanged = true;
}
break;
case INTERRUPT_FRAME:
if(eventValue != interruptFrame){
interruptFrame = eventValue;
errorMask |= ERROR_FRAME;
}
break;
case INTERRUPT_OVERRUN:
if(eventValue != interruptOverrun){
interruptOverrun = eventValue;
errorMask |= ERROR_OVERRUN;
}
break;
case INTERRUPT_PARITY:
if(eventValue != interruptParity){
interruptParity = eventValue;
errorMask |= ERROR_PARITY;
}
if((mask & MASK_ERR) == MASK_ERR && errorMask != 0){
eventType = MASK_ERR;
eventValue = errorMask;
sendEvent = true;
}
break;
case MASK_CTS:
if(eventValue != preCTS){
preCTS = eventValue;
if((mask & MASK_CTS) == MASK_CTS){
sendEvent = true;
}
}
break;
case MASK_DSR:
if(eventValue != preDSR){
preDSR = eventValue;
if((mask & MASK_DSR) == MASK_DSR){
sendEvent = true;
}
}
break;
case MASK_RING:
if(eventValue != preRING){
preRING = eventValue;
if((mask & MASK_RING) == MASK_RING){
sendEvent = true;
}
}
break;
case MASK_RLSD: /*DCD*/
if(eventValue != preRLSD){
preRLSD = eventValue;
if((mask & MASK_RLSD) == MASK_RLSD){
sendEvent = true;
}
}
break;
case MASK_RXCHAR:
if(((mask & MASK_RXCHAR) == MASK_RXCHAR) && (eventValue > 0)){
sendEvent = true;
}
break;
/*case MASK_RXFLAG:
//Do nothing at this moment
if(((mask & MASK_RXFLAG) == MASK_RXFLAG) && (eventValue > 0)){
sendEvent = true;
}
break;*/
case MASK_TXEMPTY:
if(((mask & MASK_TXEMPTY) == MASK_TXEMPTY) && (eventValue == 0) && interruptTxChanged){
sendEvent = true;
}
break;
}
if(sendEvent){
eventListener.serialEvent(new SerialPortEvent(SerialPort.this, eventType, eventValue));
}
}
}
//Need to sleep some time
try {
Thread.sleep(0, 100);
}
catch (Exception ex) {
//Do nothing
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy