?? serialport.java
字號:
// SMSLib for Java v3
// A Java API library for sending and receiving SMS via a GSM modem
// or other supported gateways.
// Web Site: http://www.smslib.org
//
// Copyright (C) 2002-2009, Thanasis Delenikas, Athens/GREECE.
// SMSLib is distributed under the terms of the Apache License version 2.0
//
// 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 org.smslib.helper;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* An RS-232 serial communications port.
* <p>
* <b>Please note: </b>This is a wrapper around
* <code>javax.comm.SerialPort</code> (and so <code>gnu.io.SerialPort</code>).
* The API definition is taken from Sun. So honor them!
* </p>
* <code>SerialPort</code> describes the low-level interface to a serial
* communications port made available by the underlying system.
* <code>SerialPort</code> defines the minimum required functionality for
* serial communications ports.
*
* @author gwellisch
*/
public class SerialPort
{
/**
* Wrapper for SerialPortEventListeners
*/
private class SerialPortEventListenerHandler implements InvocationHandler
{
private SerialPortEventListener realListenerObject;
public SerialPortEventListenerHandler(SerialPortEventListener realListenerObj)
{
this.realListenerObject = realListenerObj;
}
/**
* It's a simple interfaces. just call the only available method with
* the (only) given argument
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
this.realListenerObject.serialEvent(new SerialPortEvent(args[0]));
// The original interfaces is void
return null;
}
}
static private Class<?> classSerialPort;
/** RTS/CTS flow control on input. */
public static final int FLOWCONTROL_RTSCTS_IN;
/** 8 data bit format. */
public static final int DATABITS_8;
/** Number of STOP bits - 1. */
public static final int STOPBITS_1;
/** No parity bit. */
public static final int PARITY_NONE;
/** RTS/CTS flow control on output. */
public static final int FLOWCONTROL_RTSCTS_OUT;
static
{
try
{
classSerialPort = Class.forName("javax.comm.SerialPort");
}
catch (ClassNotFoundException e1)
{
try
{
classSerialPort = Class.forName("gnu.io.SerialPort");
}
catch (ClassNotFoundException e2)
{
throw new RuntimeException("SerialPort class not found");
}
}
try
{
// get the value of constants
Field f;
f = classSerialPort.getField("FLOWCONTROL_RTSCTS_IN");
FLOWCONTROL_RTSCTS_IN = f.getInt(null);
f = classSerialPort.getField("DATABITS_8");
DATABITS_8 = f.getInt(null);
f = classSerialPort.getField("STOPBITS_1");
STOPBITS_1 = f.getInt(null);
f = classSerialPort.getField("PARITY_NONE");
PARITY_NONE = f.getInt(null);
f = classSerialPort.getField("FLOWCONTROL_RTSCTS_OUT");
FLOWCONTROL_RTSCTS_OUT = f.getInt(null);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
private Object realObject;
protected SerialPort(Object myRealObject)
{
this.realObject = myRealObject;
}
/**
* Registers a SerialPortEventListener object to listen for SerialEvents.
* Interest in specific events may be expressed using the notifyOnXXX calls.
* The serialEvent method of SerialPortEventListener will be called with a
* SerialEvent object describing the event. The current implementation only
* allows one listener per SerialPort. Once a listener is registered,
* subsequent call attempts to addEventListener will throw a
* TooManyListenersException without effecting the listener already
* registered. All the events received by this listener are generated by one
* dedicated thread that belongs to the SerialPort object. After the port is
* closed, no more event will be generated. Another call to open() of the
* port's CommPortIdentifier object will return a new CommPort object, and
* the lsnr has to be added again to the new CommPort object to receive
* event from this port.
*
* @param lsnr
* The SerialPortEventListener object whose serialEvent method
* will be called with a SerialEvent describing the event.
* @throws java.util.TooManyListenersException
* (Wrapped as RuntimeException) If an initial attempt to attach
* a listener succeeds, subsequent attempts will throw
* TooManyListenersException without effecting the first
* listener.
*/
public void addEventListener(final SerialPortEventListener lsnr)
{
try
{
Method method = ReflectionHelper.getMethodOnlyByName(classSerialPort, "addEventListener");
// Determine the exact interface argument type (javax.comm.SerialPortEventListener or gnu.io.SerialPortEventListener)
Class<?> eventI = method.getParameterTypes()[0];
InvocationHandler handler = new SerialPortEventListenerHandler(lsnr);
// Create proxy class on the found interface type
Class<?> proxyClass = Proxy.getProxyClass(eventI.getClassLoader(), eventI);
// Bind our proxy object to the original addListener
method.invoke(this.realObject, proxyClass.getConstructor(InvocationHandler.class).newInstance(handler));
}
catch (InvocationTargetException e)
{
throw new RuntimeException(new RuntimeException(e.getTargetException().toString()));
}
catch (Exception e) // Catching exception isn't nice, but sufficient here.
{
throw new RuntimeException(e);
}
}
/**
* Closes the communications port. The application must call
* <code>close</code> when it is done with the port. Notification of this
* ownership change will be propagated to all classes registered using
* <code>addPortOwnershipListener</code>.
*/
public void close()
{
try
{
Method method = classSerialPort.getMethod("close", (java.lang.Class[]) null);
method.invoke(this.realObject);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(new RuntimeException(e.getTargetException().toString()));
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* Enables receive threshold, if this feature is supported by the driver.
* When the receive threshold condition becomes true, a read from the input
* stream for this port will return immediately. enableReceiveThreshold is
* an advisory method which the driver may not implement. By default,
* receive threshold is not enabled. An application can determine whether
* the driver supports this feature by first calling the
* enableReceiveThreshold method and then calling the
* isReceiveThresholdEnabled method. If isReceiveThresholdEnabled still
* returns false, then receive threshold is not supported by the driver. If
* the driver does not implement this feature, it will return from blocking
* reads at an appropriate time. See getInputStream for description of exact
* behaviour.
*
* @param i
* when this many bytes are in the input buffer, return
* immediately from read.
* @throws UnsupportedCommOperationException -
* (Wrapped as RuntimeException) is thrown if receive threshold
* is not supported by the underlying driver.
*/
public void enableReceiveThreshold(int i)
{
try
{
Method method = classSerialPort.getMethod("enableReceiveThreshold", int.class);
method.invoke(this.realObject, i);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(new RuntimeException(e.getTargetException().toString()));
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* Enables receive timeout, if this feature is supported by the driver. When
* the receive timeout condition becomes true, a <code>read</code> from
* the input stream for this port will return immediately.
* <p>
* <code>enableReceiveTimeout</code> is an advisory method which the
* driver may not implement. By default, receive timeout is not enabled.
* </p>
* <p>
* An application can determine whether the driver supports this feature by
* first calling the <code>enableReceiveTimeout</code> method and then
* calling the <code>isReceiveTimeout</code> method. If
* <code>isReceiveTimeout</code> still returns false, then receive timeout
* is not supported by the driver.
* </p>
* <p>
* See <code>getInputStream</code> for description of exact behaviour.
* </p>
*
* @param rcvTimeout
* when this many milliseconds have elapsed, return immediately
* from read, regardless of bytes in input buffer.
*/
public void enableReceiveTimeout(int rcvTimeout)
{
Class<?>[] paramTypes = new Class<?>[] { int.class };
try
{
Method method = classSerialPort.getMethod("enableReceiveTimeout", paramTypes);
method.invoke(this.realObject, rcvTimeout);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(new RuntimeException(e.getTargetException().toString()));
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* Returns an input stream. This is the only way to receive data from the
* communications port. If the port is unidirectional and doesn't support
* receiving data, then <CODE>getInputStream</CODE> returns null.
* <P>
* The read behaviour of the input stream returned by
* <CODE>getInputStream</CODE> depends on combination of the threshold and
* timeout values. The possible behaviours are described in the table below:
* <P>
* <table border="1">
* <tr>
* <th colspan=2>Threshold</th>
* <th colspan=2>Timeout</th>
* <th rowspan=2>Read Buffer Size</th>
* <th rowspan=2>Read Behaviour</th>
* </tr>
* <tr>
* <th>State</th>
* <th>Value</th>
* <th>State</th>
* <th>Value</th>
* </tr>
* <tr>
* <td> disabled </td>
* <td> - </td>
* <td> disabled </td>
* <td> - </td>
* <td> n bytes </td>
* <td> block until any data is available </td>
* </tr>
* <tr>
* <td> enabled </td>
* <td> m bytes </td>
* <td> disabled </td>
* <td> - </td>
* <td> n bytes </td>
* <td> block until min(<I>m</I>,<I>n</I>) bytes are available </td>
* </tr>
* <tr>
* <td> disabled </td>
* <td> - </td>
* <td> enabled </td>
* <td> x ms </td>
* <td> n bytes </td>
* <td> block for <I>x</I> ms or until any data is available </td>
* </tr>
* <tr>
* <td> enabled </td>
* <td> m bytes </td>
* <td> enabled </td>
* <td> x ms </td>
* <td> n bytes </td>
* <td> block for <I>x</I> ms or until min(<I>m</I>,<I>n</I>) bytes are
* available </td>
* </tr>
* </table>
* <P>
* Note, however, that framing errors may cause the Timeout and Threshold
* values to complete prematurely without raising an exception.
* <P>
* Enabling the Timeout OR Threshold with a value a zero is a special case.
* This causes the underlying driver to poll for incoming data instead being
* event driven. Otherwise, the behaviour is identical to having both the
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -