All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.digi.xbee.api.connection.serial.AbstractSerialPort Maven / Gradle / Ivy

There is a newer version: 1.3.2
Show newest version
/**
 * Copyright 2017, Digi International Inc.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
package com.digi.xbee.api.connection.serial;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.digi.xbee.api.connection.IConnectionInterface;
import com.digi.xbee.api.exceptions.ConnectionException;
import com.digi.xbee.api.exceptions.InvalidConfigurationException;

/**
 * Abstract class that provides common functionality to work with serial ports.
 */
public abstract class AbstractSerialPort implements IConnectionInterface {
	
	// Constants.
	/**
	 * Default receive timeout: {@value} seconds.
	 * 
	 * 

When the specified number of milliseconds have elapsed, read will * return immediately.

*/ public static final int DEFAULT_PORT_TIMEOUT = 10; /** * Default number of data bits: {@value}. */ public static final int DEFAULT_DATA_BITS = 8; /** * Default number of stop bits: {@value}. */ public static final int DEFAULT_STOP_BITS = 1; /** * Default parity: {@value} (None). */ public static final int DEFAULT_PARITY = 0; /** * Default flow control: {@value} (None). */ public static final int DEFAULT_FLOW_CONTROL = 0; protected static final int FLOW_CONTROL_HW = 3; protected static final String PORT_ALIAS = "Serial Port"; // Variables. protected String port; protected int baudRate; protected int receiveTimeout; protected SerialPortParameters parameters; protected boolean connectionOpen = false; private Logger logger; /** * Class constructor. Instantiates a new {@code AbstractSerialPort} object * with the given parameters. * * @param port COM port name to use. * @param parameters Serial port connection parameters. * * @throws IllegalArgumentException if {@code port.length == 0}. * @throws NullPointerException if {@code port == null} or * if {@code parameters == null}. * * @see #AbstractSerialPort(String, int) * @see #AbstractSerialPort(String, int, int) * @see #AbstractSerialPort(String, SerialPortParameters, int) * @see SerialPortParameters */ protected AbstractSerialPort(String port, SerialPortParameters parameters) { this(port, parameters, DEFAULT_PORT_TIMEOUT); } /** * Class constructor. Instantiates a new {@code AbstractSerialPort} object * with the given parameters. * * @param port COM port name to use. * @param baudRate Serial connection baud rate, the rest of parameters will * be set by default. * * @throws IllegalArgumentException if {@code port.length == 0} or * if {@code baudRate < 0}. * @throws NullPointerException if {@code port == null}. * * @see #DEFAULT_DATA_BITS * @see #DEFAULT_FLOW_CONTROL * @see #DEFAULT_PARITY * @see #DEFAULT_STOP_BITS * @see #DEFAULT_PORT_TIMEOUT * @see #AbstractSerialPort(String, int, int) * @see #AbstractSerialPort(String, SerialPortParameters) * @see #AbstractSerialPort(String, SerialPortParameters, int) */ protected AbstractSerialPort(String port, int baudRate) { this(port, new SerialPortParameters(baudRate, DEFAULT_DATA_BITS, DEFAULT_STOP_BITS, DEFAULT_PARITY, DEFAULT_FLOW_CONTROL), DEFAULT_PORT_TIMEOUT); } /** * Class constructor. Instantiates a new {@code AbstractSerialPort} object * with the given parameters. * * @param port COM port name to use. * @param baudRate Serial port baud rate, the rest of parameters will be * set by default. * @param receiveTimeout Receive timeout in milliseconds. * * @throws IllegalArgumentException if {@code port.length == 0} or * if {@code baudRate < 0} or * if {@code receiveTimeout < 0}. * @throws NullPointerException if {@code port == null}. * * @see DEFAULT_DATA_BITS * @see DEFAULT_FLOW_CONTROL * @see DEFAULT_PARITY * @see DEFAULT_STOP_BITS * @see #AbstractSerialPort(String, int) * @see #AbstractSerialPort(String, SerialPortParameters) * @see #AbstractSerialPort(String, SerialPortParameters, int) */ protected AbstractSerialPort(String port, int baudRate, int receiveTimeout) { this(port, new SerialPortParameters(baudRate, DEFAULT_DATA_BITS, DEFAULT_STOP_BITS, DEFAULT_PARITY, DEFAULT_FLOW_CONTROL), receiveTimeout); } /** * Class constructor. Instantiates a new {@code AbstractSerialPort} object * with the given parameters. * * @param port COM port name to use. * @param parameters Serial port connection parameters. * @param receiveTimeout Serial connection receive timeout in milliseconds. * * @throws IllegalArgumentException if {@code port.length == 0} or * if {@code receiveTimeout < 0}. * @throws NullPointerException if {@code port == null} or * if {@code parameters == null}. * * @see #AbstractSerialPort(String, int) * @see #AbstractSerialPort(String, int, int) * @see #AbstractSerialPort(String, SerialPortParameters) * @see SerialPortParameters */ protected AbstractSerialPort(String port, SerialPortParameters parameters, int receiveTimeout) { if (port == null) throw new NullPointerException("Serial port cannot be null."); if (parameters == null) throw new NullPointerException("SerialPortParameters cannot be null."); if (port.length() == 0) throw new IllegalArgumentException("Serial port cannot be an empty string."); if (receiveTimeout < 0) throw new IllegalArgumentException("Receive timeout cannot be less than 0."); this.port = port; this.baudRate = parameters.baudrate; this.receiveTimeout = receiveTimeout; this.parameters = parameters; this.logger = LoggerFactory.getLogger(AbstractSerialPort.class); } /* * (non-Javadoc) * @see com.digi.xbee.api.connection.IConnectionInterface#isOpen() */ @Override public boolean isOpen() { return connectionOpen; } /** * Returns the name of the serial port. * * @return Port name. */ public String getPort() { return port; } /** * Sets the state of the DTR. * * @param state {@code true} to set the line status high, {@code false} to * set it low. * * @see #isCD() * @see #isCTS() * @see #isDSR() * @see #setRTS(boolean) */ public abstract void setDTR(boolean state); /** * Sets the state of the RTS line. * * @param state {@code true} to set the line status high, {@code false} to * set it low. * * @see #isCD() * @see #isCTS() * @see #isDSR() * @see #setDTR(boolean) */ public abstract void setRTS(boolean state); /** * Returns the state of the CTS line. * * @return {@code true} if the line is high, {@code false} otherwise. * * @see #isCD() * @see #isDSR() * @see #setDTR(boolean) * @see #setRTS(boolean) */ public abstract boolean isCTS(); /** * Returns the state of the DSR line. * * @return {@code true} if the line is high, {@code false} otherwise. * * @see #isCD() * @see #isCTS() * @see #setDTR(boolean) * @see #setRTS(boolean) */ public abstract boolean isDSR(); /** * Returns the state of the CD line. * * @return {@code true} if the line is high, {@code false} otherwise. * * @see #isCTS() * @see #isDSR() * @see #setDTR(boolean) * @see #setRTS(boolean) */ public abstract boolean isCD(); /** * Returns whether or not the port's flow control is configured in * hardware mode. * * @return {@code true} if the flow control is hardware, {@code false} * otherwise. * * @see #getPortParameters() * @see #setPortParameters(SerialPortParameters) * @see #setPortParameters(int, int, int, int, int) */ public boolean isHardwareFlowControl() { return parameters.flowControl == FLOW_CONTROL_HW; } /** * Sets the new parameters of the serial port. * * @param baudRate The new value of baud rate. * @param dataBits The new value of data bits. * @param stopBits The new value of stop bits. * @param parity The new value of parity. * @param flowControl The new value of flow control. * * @throws ConnectionException if any error occurs when setting the serial * port parameters * @throws IllegalArgumentException if {@code baudRate < 0} or * if {@code dataBits < 0} or * if {@code stopBits < 0} or * if {@code parity < 0} or * if {@code flowControl < 0}. * @throws InvalidConfigurationException if the configuration is invalid. * * @see #getPortParameters() * @see #setPortParameters(SerialPortParameters) */ public void setPortParameters(int baudRate, int dataBits, int stopBits, int parity, int flowControl) throws InvalidConfigurationException, ConnectionException { SerialPortParameters parameters = new SerialPortParameters(baudRate, dataBits, stopBits, parity, flowControl); setPortParameters(parameters); } /** * Sets the new parameters of the serial port as * {@code SerialPortParameters}. * * @param parameters The new serial port parameters. * * @throws ConnectionException if any error occurs when setting the serial * port parameters. * @throws InvalidConfigurationException if the configuration is invalid. * @throws NullPointerException if {@code parameters == null}. * * @see #getPortParameters() * @see #setPortParameters(int, int, int, int, int) * @see SerialPortParameters */ public void setPortParameters(SerialPortParameters parameters) throws InvalidConfigurationException, ConnectionException { if (parameters == null) throw new NullPointerException("Serial port parameters cannot be null."); baudRate = parameters.baudrate; this.parameters = parameters; if (isOpen()) { close(); open(); } } /** * Enables or disables the break line. * * @param enabled {@code true} to enable the Break line, {@code false} to * disable it. * * @see #sendBreak(int) */ public abstract void setBreak(boolean enabled); /** * Sends a break signal to the serial port with the given duration * (in milliseconds). * * @param duration Duration of the break signal in milliseconds. * * @see #setBreak(boolean) */ public abstract void sendBreak(int duration); /** * Sets the read timeout of the serial port (in milliseconds). * * @param timeout The new read timeout of the serial port in milliseconds. * * @see #getReadTimeout() */ public abstract void setReadTimeout(int timeout); /** * Returns the read timeout of the serial port (in milliseconds). * * @return The read timeout of the serial port in milliseconds. * * @see #setReadTimeout(int) */ public abstract int getReadTimeout(); /** * Purges the serial port removing all the data from the input stream. * * @see #flush() */ public void purge() { if (getInputStream() != null) { try { byte[] availableBytes = new byte[getInputStream().available()]; if (getInputStream().available() > 0) getInputStream().read(availableBytes, 0, getInputStream().available()); } catch (IOException e) { logger.error(e.getMessage(), e); } } } /** * Flushes the available data of the output stream. * * @see #purge() */ public void flush() { if (getOutputStream() != null) { try { getOutputStream().flush(); } catch (IOException e) { logger.error(e.getMessage(), e); } } } /* * (non-Javadoc) * @see com.digi.xbee.api.connection.IConnectionInterface#writeData(byte[]) */ @Override public void writeData(byte[] data) throws IOException { if (data == null) throw new NullPointerException("Data to be sent cannot be null."); if (getOutputStream() != null) { // Writing data in ports without any device connected and configured with // hardware flow-control causes the majority of serial libraries to hang. // Before writing any data, check if the port is configured with hardware // flow-control and, if so, try to write the data up to 3 times verifying // that the CTS line is high (there is a device connected to the other side // ready to receive data). if (isHardwareFlowControl()) { int tries = 0; while (tries < 3 && !isCTS()) { try { Thread.sleep(100); } catch (InterruptedException e) { } tries += 1; } if (isCTS()) { getOutputStream().write(data); getOutputStream().flush(); } } else { getOutputStream().write(data); getOutputStream().flush(); } } } /* * (non-Javadoc) * @see com.digi.xbee.api.connection.IConnectionInterface#writeData(byte[], int, int) */ @Override public void writeData(byte[] data, int offset, int length) throws IOException { if (data == null) throw new NullPointerException("Data to be sent cannot be null."); if (offset < 0) throw new IllegalArgumentException("Offset cannot be less than 0."); if (length < 1) throw new IllegalArgumentException("Length cannot be less than 1."); if (offset >= data.length) throw new IllegalArgumentException("Offset must be less than the data length."); if (offset + length > data.length) throw new IllegalArgumentException("Offset + length cannot be great than the data length."); if (getOutputStream() != null) { // Writing data in ports without any device connected and configured with // hardware flow-control causes the majority of serial libraries to hang. // Before writing any data, check if the port is configured with hardware // flow-control and, if so, try to write the data up to 3 times verifying // that the CTS line is high (there is a device connected to the other side // ready to receive data). if (isHardwareFlowControl()) { int tries = 0; while (tries < 3 && !isCTS()) { try { Thread.sleep(100); } catch (InterruptedException e) { } tries += 1; } if (isCTS()) { getOutputStream().write(data, offset, length); getOutputStream().flush(); } } else { getOutputStream().write(data, offset, length); getOutputStream().flush(); } } } /* * (non-Javadoc) * @see com.digi.xbee.api.connection.IConnectionInterface#readData(byte[]) */ @Override public int readData(byte[] data) throws IOException { if (data == null) throw new NullPointerException("Buffer cannot be null."); int readBytes = 0; if (getInputStream() != null) readBytes = getInputStream().read(data); return readBytes; } /* * (non-Javadoc) * @see com.digi.xbee.api.connection.IConnectionInterface#readData(byte[], int, int) */ @Override public int readData(byte[] data, int offset, int length) throws IOException { if (data == null) throw new NullPointerException("Buffer cannot be null."); if (offset < 0) throw new IllegalArgumentException("Offset cannot be less than 0."); if (length < 1) throw new IllegalArgumentException("Length cannot be less than 1."); if (offset >= data.length) throw new IllegalArgumentException("Offset must be less than the buffer length."); if (offset + length > data.length) throw new IllegalArgumentException("Offset + length cannot be great than the buffer length."); int readBytes = 0; if (getInputStream() != null) readBytes = getInputStream().read(data, offset, length); return readBytes; } /** * Returns the XBee serial port parameters. * * @return The XBee serial port parameters. * * @see #setPortParameters(SerialPortParameters) * @see #setPortParameters(int, int, int, int, int) * @see SerialPortParameters */ public SerialPortParameters getPortParameters() { if (parameters != null) return parameters; return new SerialPortParameters(baudRate, DEFAULT_DATA_BITS, DEFAULT_STOP_BITS, DEFAULT_PARITY, DEFAULT_FLOW_CONTROL); } /** * Returns the serial port receive timeout (in milliseconds). * * @return The serial port receive timeout in milliseconds. * * @see #getReadTimeout() * @see #setReadTimeout(int) */ public int getReceiveTimeout() { return receiveTimeout; } /* * (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { if (parameters != null) { String parity = "N"; String flowControl = "N"; if (parameters.parity == 1) parity = "O"; else if (parameters.parity == 2) parity = "E"; else if (parameters.parity == 3) parity = "M"; else if (parameters.parity == 4) parity = "S"; if (parameters.flowControl == 1 || parameters.flowControl == 2 || parameters.flowControl == 3) flowControl = "H"; else if (parameters.flowControl == 4 || parameters.flowControl == 8 || parameters.flowControl == 12) flowControl = "S"; return "[" + port + " - " + baudRate + "/" + parameters.dataBits + "/" + parity + "/" + parameters.stopBits + "/" + flowControl + "] "; } else return "[" + port + " - " + baudRate + "/8/N/1/N] "; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy