/*** * Copyright 2002-2010 jamod development team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ***/ package net.wimpi.modbus.util; import java.util.Properties; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.StandardToStringStyle; import org.apache.commons.lang.builder.ToStringBuilder; import gnu.io.SerialPort; import net.wimpi.modbus.Modbus; /** * Helper class wrapping all serial port communication parameters. * Very similar to the gnu.io demos, however, not the same. * * @author Dieter Wimberger * @author John Charlton * @version @version@ (@date@) */ public class SerialParameters { public static int DEFAULT_RECEIVE_TIMEOUT_MILLIS = 1500; // 1.5 secs // instance attributes private String m_PortName; private int m_BaudRate; private int m_FlowControlIn; private int m_FlowControlOut; private int m_Databits; private int m_Stopbits; private int m_Parity; private String m_Encoding; private boolean m_Echo; private int m_ReceiveTimeoutMillis; private static StandardToStringStyle toStringStyle = new StandardToStringStyle(); static { toStringStyle.setUseShortClassName(true); } /** * Constructs a new <tt>SerialParameters</tt> instance with * default values: 9600 boud - 8N1 - ASCII. */ public SerialParameters() { this("", 9600, SerialPort.FLOWCONTROL_NONE, SerialPort.FLOWCONTROL_NONE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE, Modbus.DEFAULT_SERIAL_ENCODING, false, DEFAULT_RECEIVE_TIMEOUT_MILLIS); }// constructor /** * Constructs a new <tt>SerialParameters<tt> instance with * given parameters. * * @param portName The name of the port. * @param baudRate The baud rate. * @param flowControlIn Type of flow control for receiving. * @param flowControlOut Type of flow control for sending. * @param databits The number of data bits. * @param stopbits The number of stop bits. * @param encoding * @param parity The type of parity. * @param echo Flag for setting the RS485 echo mode. * @param receiveTimeoutMillis timeout in milliseconds for read operations */ public SerialParameters(String portName, int baudRate, int flowControlIn, int flowControlOut, int databits, int stopbits, int parity, String encoding, boolean echo, int receiveTimeoutMillis) { setPortName(portName); setBaudRate(baudRate); setFlowControlIn(flowControlIn); setFlowControlOut(flowControlOut); setDatabits(databits); setStopbits(stopbits); setParity(parity); setEncoding(encoding); setEcho(echo); setReceiveTimeoutMillis(receiveTimeoutMillis); }// constructor @Override public String toString() { return new ToStringBuilder(this, toStringStyle).append("portName", m_PortName).append("baudRate", m_BaudRate) .append("flowControlIn", getFlowControlInString()).append("flowControlOut", getFlowControlOutString()) .append("databits", getDatabitsString()).append("stopbits", getStopbitsString()) .append("parity", getParityString()).append("encoding", m_Encoding).append("echo", m_Echo) .append("receiveTimeoutMillis", m_ReceiveTimeoutMillis).toString(); } @Override public int hashCode() { return new HashCodeBuilder(7, 51).append(m_PortName).append(m_BaudRate).append(m_FlowControlIn) .append(m_FlowControlOut).append(m_Databits).append(m_Stopbits).append(m_Parity).append(m_Encoding) .append(m_Echo).append(m_ReceiveTimeoutMillis).toHashCode(); } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (obj == this) { return true; } if (obj.getClass() != getClass()) { return false; } SerialParameters rhs = (SerialParameters) obj; return new EqualsBuilder().append(m_PortName, rhs.m_PortName).append(m_BaudRate, rhs.m_BaudRate) .append(m_FlowControlIn, rhs.m_FlowControlIn).append(m_FlowControlOut, rhs.m_FlowControlOut) .append(m_Databits, rhs.m_Databits).append(m_Stopbits, rhs.m_Stopbits).append(m_Parity, rhs.m_Parity) .append(m_Encoding, rhs.m_Encoding).append(m_Echo, rhs.m_Echo) .append(m_ReceiveTimeoutMillis, rhs.m_ReceiveTimeoutMillis).isEquals(); } /** * Constructs a new <tt>SerialParameters</tt> instance with * parameters obtained from a <tt>Properties</tt> instance. * * @param props a <tt>Properties</tt> instance. * @param prefix a prefix for the properties keys if embedded into * other properties. */ public SerialParameters(Properties props, String prefix) { if (prefix == null) { prefix = ""; } setPortName(props.getProperty(prefix + "portName", "")); setBaudRate(props.getProperty(prefix + "baudRate", "" + 9600)); setFlowControlIn(props.getProperty(prefix + "flowControlIn", "" + SerialPort.FLOWCONTROL_NONE)); setFlowControlOut(props.getProperty(prefix + "flowControlOut", "" + SerialPort.FLOWCONTROL_NONE)); setParity(props.getProperty(prefix + "parity", "" + SerialPort.PARITY_NONE)); setDatabits(props.getProperty(prefix + "databits", "" + SerialPort.DATABITS_8)); setStopbits(props.getProperty(prefix + "stopbits", "" + SerialPort.STOPBITS_1)); setEncoding(props.getProperty(prefix + "encoding", Modbus.DEFAULT_SERIAL_ENCODING)); setEcho("true".equals(props.getProperty(prefix + "echo"))); setReceiveTimeoutMillis(props.getProperty(prefix + "timeout", "" + 500)); }// constructor /** * Sets the port name. * * @param name the new port name. */ public void setPortName(String name) { m_PortName = name; }// setPortName /** * Returns the port name. * * @return the port name. */ public String getPortName() { return m_PortName; }// getPortName /** * Sets the baud rate. * * @param rate the new baud rate. */ public void setBaudRate(int rate) throws IllegalArgumentException { if (!SerialParameterValidator.isBaudRateValid(rate)) { throw new IllegalArgumentException("invalid baud rate: " + Integer.toString(rate)); } m_BaudRate = rate; }// setBaudRate /** * Sets the baud rate. * * @param rate the new baud rate. */ public void setBaudRate(String rate) throws IllegalArgumentException { int intBaudRate = 0; try { intBaudRate = Integer.parseInt(rate); } catch (NumberFormatException e) { throw new IllegalArgumentException( "baudString '" + rate + "' can not be converted to a number: " + e.getMessage()); } setBaudRate(intBaudRate); }// setBaudRate /** * Return the baud rate as <tt>int</tt>. * * @return the baud rate as <tt>int</tt>. */ public int getBaudRate() { return m_BaudRate; }// getBaudRate /** * Returns the baud rate as a <tt>String</tt>. * * @return the baud rate as <tt>String</tt>. */ public String getBaudRateString() { return Integer.toString(m_BaudRate); }// getBaudRateString /** * Sets the type of flow control for the input * as given by the passed in <tt>int</tt>. * * @param flowcontrol the new flow control type. */ public void setFlowControlIn(int flowcontrol) throws IllegalArgumentException { if (!SerialParameterValidator.isFlowControlValid(flowcontrol)) { throw new IllegalArgumentException("flowcontrol int '" + flowcontrol + "' invalid"); } m_FlowControlIn = flowcontrol; }// setFlowControl /** * Sets the type of flow control for the input * as given by the passed in <tt>String</tt>. * * @param flowcontrol the flow control for reading type. */ public void setFlowControlIn(String flowcontrol) throws IllegalArgumentException { if (!SerialParameterValidator.isFlowControlValid(flowcontrol)) { throw new IllegalArgumentException("flowcontrolIn string '" + flowcontrol + "' unknown"); } setFlowControlIn(stringToFlow(flowcontrol)); }// setFlowControlIn /** * Returns the input flow control type as <tt>int</tt>. * * @return the input flow control type as <tt>int</tt>. */ public int getFlowControlIn() { return m_FlowControlIn; }// getFlowControlIn /** * Returns the input flow control type as <tt>String</tt>. * * @return the input flow control type as <tt>String</tt>. */ public String getFlowControlInString() { return flowToString(m_FlowControlIn); }// getFlowControlIn /** * Sets the output flow control type as given * by the passed in <tt>int</tt>. * * @param flowControlOut new output flow control type as <tt>int</tt>. */ public void setFlowControlOut(int flowControlOut) throws IllegalArgumentException { if (!SerialParameterValidator.isFlowControlValid(flowControlOut)) { throw new IllegalArgumentException("flowcontrol int '" + flowControlOut + "' unknown"); } m_FlowControlOut = flowControlOut; }// setFlowControlOut /** * Sets the output flow control type as given * by the passed in <tt>String</tt>. * * @param flowControlOut the new output flow control type as <tt>String</tt>. */ public void setFlowControlOut(String flowControlOut) throws IllegalArgumentException { if (!SerialParameterValidator.isFlowControlValid(flowControlOut)) { throw new IllegalArgumentException("flowcontrol string '" + flowControlOut + "' unknown"); } m_FlowControlOut = stringToFlow(flowControlOut); }// setFlowControlOut /** * Returns the output flow control type as <tt>int</tt>. * * @return the output flow control type as <tt>int</tt>. */ public int getFlowControlOut() { return m_FlowControlOut; }// getFlowControlOut /** * Returns the output flow control type as <tt>String</tt>. * * @return the output flow control type as <tt>String</tt>. */ public String getFlowControlOutString() { return flowToString(m_FlowControlOut); }// getFlowControlOutString /** * Sets the number of data bits. * * @param databits the new number of data bits. */ public void setDatabits(int databits) throws IllegalArgumentException { if (!SerialParameterValidator.isDataBitsValid(databits)) { throw new IllegalArgumentException("Databit '" + databits + "' invalid"); } switch (databits) { case 5: m_Databits = SerialPort.DATABITS_5; break; case 6: m_Databits = SerialPort.DATABITS_6; break; case 7: m_Databits = SerialPort.DATABITS_7; break; case 8: m_Databits = SerialPort.DATABITS_8; break; default: m_Databits = SerialPort.DATABITS_8; break; } }// setDatabits /** * Sets the number of data bits from the given <tt>String</tt>. * * @param databits the new number of data bits as <tt>String</tt>. */ public void setDatabits(String databits) throws IllegalArgumentException { int intDataBits = 0; try { intDataBits = Integer.parseInt(databits); } catch (NumberFormatException e) { throw new IllegalArgumentException( "databitsString '" + databits + "' can not be converted to a number: " + e.getMessage()); } setDatabits(intDataBits); }// setDatabits /** * Returns the number of data bits as <tt>int</tt>. * * @return the number of data bits as <tt>int</tt>. */ public int getDatabits() { return m_Databits; }// getDatabits /** * Returns the number of data bits as <tt>String</tt>. * * @return the number of data bits as <tt>String</tt>. */ public String getDatabitsString() { switch (m_Databits) { case SerialPort.DATABITS_5: return "5"; case SerialPort.DATABITS_6: return "6"; case SerialPort.DATABITS_7: return "7"; case SerialPort.DATABITS_8: return "8"; default: return "8"; } }// getDataBits /** * Sets the number of stop bits. * * @param stopbits the new number of stop bits setting. */ public void setStopbits(double stopbits) throws IllegalArgumentException { if (!SerialParameterValidator.isStopbitsValid(stopbits)) { throw new IllegalArgumentException("stopbit value '" + stopbits + "' not valid"); } if (stopbits == 1) { m_Stopbits = SerialPort.STOPBITS_1; } else if (stopbits == 1.5) { m_Stopbits = SerialPort.STOPBITS_1_5; } else if (stopbits == 2) { m_Stopbits = SerialPort.STOPBITS_2; } else { m_Stopbits = SerialPort.STOPBITS_1; } }// setStopbits /** * Sets the number of stop bits from the given <tt>String</tt>. * * @param stopbits the number of stop bits as <tt>String</tt>. */ public void setStopbits(String stopbits) throws IllegalArgumentException { double doubleStopBits = 1.0; try { doubleStopBits = Double.parseDouble(stopbits); } catch (NumberFormatException e) { throw new IllegalArgumentException( "stopbitsString '" + stopbits + "' can not be converted to a number: " + e.getMessage()); } setStopbits(doubleStopBits); }// setStopbits /** * Returns the number of stop bits as <tt>int</tt>. * * @return the number of stop bits as <tt>int</tt>. */ public int getStopbits() { return m_Stopbits; }// getStopbits /** * Returns the number of stop bits as <tt>String</tt>. * * @return the number of stop bits as <tt>String</tt>. */ public String getStopbitsString() { switch (m_Stopbits) { case SerialPort.STOPBITS_1: return "1"; case SerialPort.STOPBITS_1_5: return "1.5"; case SerialPort.STOPBITS_2: return "2"; default: return "1"; } }// getStopbitsString /** * Sets the parity schema. * * @param parity the new parity schema as <tt>int</tt>. */ public void setParity(int parity) { if (!SerialParameterValidator.isParityValid(parity)) { throw new IllegalArgumentException("parity value '" + parity + "' not valid"); } m_Parity = parity; }// setParity /** * Sets the parity schema from the given * <tt>String</tt>. * * @param parity the new parity schema as <tt>String</tt>. */ public void setParity(String parity) throws IllegalArgumentException { parity = parity.toLowerCase(); int intParity = SerialPort.PARITY_NONE; if (parity.equals("none") || parity.equals("n")) { intParity = SerialPort.PARITY_NONE; } else if (parity.equals("even") || parity.equals("e")) { intParity = SerialPort.PARITY_EVEN; } else if (parity.equals("odd") || parity.equals("o")) { intParity = SerialPort.PARITY_ODD; } else { throw new IllegalArgumentException("unknown parity string '" + parity + "'"); } setParity(intParity); }// setParity /** * Returns the parity schema as <tt>int</tt>. * * @return the parity schema as <tt>int</tt>. */ public int getParity() { return m_Parity; }// getParity /** * Returns the parity schema as <tt>String</tt>. * * @return the parity schema as <tt>String</tt>. */ public String getParityString() { switch (m_Parity) { case SerialPort.PARITY_NONE: return "none"; case SerialPort.PARITY_EVEN: return "even"; case SerialPort.PARITY_ODD: return "odd"; default: return "none"; } }// getParityString /** * Sets the encoding to be used. * * @param enc the encoding as string. * @see Modbus#SERIAL_ENCODING_ASCII * @see Modbus#SERIAL_ENCODING_RTU * @see Modbus#SERIAL_ENCODING_BIN */ public void setEncoding(String enc) throws IllegalArgumentException { enc = enc.toLowerCase(); if (!SerialParameterValidator.isEncodingValid(enc)) { throw new IllegalArgumentException("encoding value '" + enc + "' not valid"); } m_Encoding = enc; }// setEncoding /** * Returns the encoding to be used. * * @return the encoding as string. * @see Modbus#SERIAL_ENCODING_ASCII * @see Modbus#SERIAL_ENCODING_RTU * @see Modbus#SERIAL_ENCODING_BIN */ public String getEncoding() { return m_Encoding; }// getEncoding /** * Get the Echo value. * * @return the Echo value. */ public boolean isEcho() { return m_Echo; }// getEcho /** * Set the Echo value. * * @param newEcho The new Echo value. */ public void setEcho(boolean newEcho) { m_Echo = newEcho; }// setEcho /** * Returns the receive timeout for serial communication. * * @return the timeout in milliseconds. */ public int getReceiveTimeoutMillis() { return m_ReceiveTimeoutMillis; }// getReceiveTimeout /** * Sets the receive timeout for serial communication. * * @param receiveTimeout the receiveTimeout in milliseconds. */ public void setReceiveTimeoutMillis(int receiveTimeout) { if (!SerialParameterValidator.isReceiveTimeoutValid(receiveTimeout)) { throw new IllegalArgumentException("negative values like '" + receiveTimeout + "' invalid as timeout"); } m_ReceiveTimeoutMillis = receiveTimeout; }// setReceiveTimeout /** * Sets the receive timeout for the serial communication * parsing the given String using <tt>Integer.parseInt(String)</tt>. * * @param str the timeout as String. */ public void setReceiveTimeoutMillis(String str) { setReceiveTimeoutMillis(Integer.parseInt(str)); }// setReceiveTimeout /** * Converts a <tt>String</tt> describing a flow control type to the * <tt>int</tt> which is defined in SerialPort. * * @param flowcontrol the <tt>String</tt> describing the flow control type. * @return the <tt>int</tt> describing the flow control type. */ private int stringToFlow(String flowcontrol) { flowcontrol = flowcontrol.toLowerCase(); if (flowcontrol.equals("none")) { return SerialPort.FLOWCONTROL_NONE; } if (flowcontrol.equals("xon/xoff out")) { return SerialPort.FLOWCONTROL_XONXOFF_OUT; } if (flowcontrol.equals("xon/xoff in")) { return SerialPort.FLOWCONTROL_XONXOFF_IN; } if (flowcontrol.equals("rts/cts in")) { return SerialPort.FLOWCONTROL_RTSCTS_IN; } if (flowcontrol.equals("rts/cts out")) { return SerialPort.FLOWCONTROL_RTSCTS_OUT; } return SerialPort.FLOWCONTROL_NONE; }// stringToFlow /** * Converts an <tt>int</tt> describing a flow control type to a * String describing a flow control type. * * @param flowcontrol the <tt>int</tt> describing the * flow control type. * @return the <tt>String</tt> describing the flow control type. */ private String flowToString(int flowcontrol) { switch (flowcontrol) { case SerialPort.FLOWCONTROL_NONE: return "none"; case SerialPort.FLOWCONTROL_XONXOFF_OUT: return "xon/xoff out"; case SerialPort.FLOWCONTROL_XONXOFF_IN: return "xon/xoff in"; case SerialPort.FLOWCONTROL_RTSCTS_IN: return "rts/cts in"; case SerialPort.FLOWCONTROL_RTSCTS_OUT: return "rts/cts out"; default: return "none"; } }// flowToString /** * Populates the settings from an <tt>Proper</tt> * that reads from a properties file or contains a * set of properties. * * @param in the <tt>InputStream</tt> to read from. * * private void loadFrom(InputStream in) throws IOException { * Properties props = new Properties(); * props.load(in); * setPortName(props.getProperty("portName")); * setBaudRate(props.getProperty("baudRate")); * setFlowControlIn(props.getProperty("flowControlIn")); * setFlowControlOut(props.getProperty("flowControlOut")); * setParity(props.getProperty("parity")); * setDatabits(props.getProperty("databits")); * setStopbits(props.getProperty("stopbits")); * setEncoding(props.getProperty("encoding")); * setEcho(new Boolean(props.getProperty("echo")).booleanValue()); * }//loadFrom * */ }// class SerialParameters