📄 serialportcomm.java
字号:
readDataAgainstTermial();
}
else if (this.delayToRead > 0)
{
readDataAfterDelay();
}
else
{
this.ensureBufferSize(available);
int readed = in.read(this.rcvBuffer, 0, available);
if (readed > 0)
{
this.handleMessage(this.rcvBuffer, 0, readed);
}
}
}
catch (Throwable ex)
{
ex.printStackTrace();
}
}
/** 固定长度方式读取数据 */
private void readDataByFixedLength(int available) throws IOException
{
int packetSize = this.packetSize;
int pckts = available / packetSize;
int prepareToRead = pckts * packetSize;//只读pckts个报文的数据
this.ensureBufferSize(prepareToRead);
byte[] rcvBuffer = this.rcvBuffer;
int readed = in.read(rcvBuffer, 0, prepareToRead);
if(readed != prepareToRead)
{//在使用gnu.io.RXTXCommDriver时就出现过readed == packetSize
// 该驱动程序对 receiveThreshold 特性的实现机制不同于com.sun.comm.Win32Driver
pckts = readed / packetSize;
}
int i = 0;
try
{
while(i < pckts)
{
handleMessage(rcvBuffer, i++ * packetSize, packetSize);
}
}
catch(InvalidMessageException e)
{//读到无效数据,则通过全部一次性读出缓冲区中的已经被破坏的数据
//来纠正,继而让发送端重发
this.port.disableReceiveThreshold();
try
{
int cntDiscard = e.cntDiscard;
if (cntDiscard <= 0)
{
cntDiscard = this.in.available();
}
this.in.read(rcvBuffer, 0, cntDiscard);
}
catch (Exception ex){}
this.configPortWithPacketSize();
}
}
/** 不明确知道报文长度的情况下,则通过结束符判断 */
private void readDataAgainstTermial() throws IOException
{
int startIndex = Math.max(cntStoredBytes - terminalBytes.length + 1, 0);
this.ensureBufferSize(cntStoredBytes + in.available());
byte[] rcvBuffer = this.rcvBuffer;
cntStoredBytes += in.read(rcvBuffer, cntStoredBytes, in.available());
try
{
//可能上次读入的数据没有全部terminalBytes,但可能包含部分,因此
//startIndex的计算应该是cntStoredBytes - terminalBytes.length + 1
int index;
// System.out.println("cntStoredBytes = " + cntStoredBytes);
while((index = indexOfFirstByte(rcvBuffer, startIndex, cntStoredBytes, terminalBytes)) >=0)
{
if(index > 0) handleMessage(rcvBuffer, 0, index);
cntStoredBytes -= (index + terminalBytes.length);
if (cntStoredBytes > 0)
{
System.arraycopy(rcvBuffer, index + terminalBytes.length, rcvBuffer, 0, cntStoredBytes);
startIndex = 0;
// System.out.println("\t" + index);
}
else
{
break;
}
}
//System.out.println("cntStoredBytes = " + cntStoredBytes);
}
catch(com.zcsoft.comm.InvalidMessageException e)
{//读到无效数据,则通过全部一次性读出缓冲区中的已经被破坏的数据
//来纠正,继而让发送端重发
this.cntStoredBytes = 0;
try
{
int cntDiscard = e.cntDiscard;
if (cntDiscard <= 0)
{
cntDiscard = this.in.available();
}
in.read(rcvBuffer, 0, cntDiscard);
}
catch (Exception ex){}
}
}
/**
* 延时指定时间后读取数据。
*/
private void readDataAfterDelay() throws IOException
{
try
{
Thread.sleep(delayToRead);
}
catch (InterruptedException ex){}
this.ensureBufferSize(in.available());
byte[] rcvBuffer = this.rcvBuffer;
int readed = in.read(rcvBuffer, 0, in.available());
try
{
handleMessage(rcvBuffer, 0, readed);
}
catch(com.zcsoft.comm.InvalidMessageException e)
{//读到无效数据,则通过全部一次性读出缓冲区中的已经被破坏的数据
//来纠正,继而让发送端重发
try
{
int cntDiscard = e.cntDiscard;
if (cntDiscard <= 0)
{
cntDiscard = this.in.available();
}
in.read(rcvBuffer, 0, cntDiscard);
}
catch (Exception ex){}
}
}
/**
* 在bytesStore中查找searchedBytes位置
* @param bytesStore 可能包含了searchedBytes的字节数组
* @param startIndex 从该位置开始查找
* @param endIndex 到此停止搜索
* @param searchedBytes 需要查找的字节数组
* @return searchedBytes[0]在bytesStore上索引。如果没有找到searchedBytes,则返回-1
*/
private static int indexOfFirstByte(byte[] bytesStore, int startIndex, int lastIndex, byte[] searchedBytes)
{
int endIndex = lastIndex - searchedBytes.length;
if (endIndex >= bytesStore.length || startIndex > endIndex)
{
return -1;
}
byte firstByte = searchedBytes[0];
startFindFirstByte:
while(true)
{
while (startIndex <= endIndex
&& bytesStore[startIndex] != firstByte)
{
startIndex ++;
}
if (startIndex > endIndex)
{
return -1;
}
int j = startIndex + 1;
int k = 1;
while (k < searchedBytes.length && j < bytesStore.length)
{
if(bytesStore[j++] != searchedBytes[k++])
{
startIndex ++;
continue startFindFirstByte;
}
}
return startIndex;
}
}
/** @param e */
private void debug(Object e)
{
System.err.println(this.portID.getName().concat(String.valueOf(e)));
}
/** 设定接收报文的长度(字节数)
*
* @param newPacketSize 大于0整数 */
private void setPacketSize(int size)
{
if(size < 0)
{
throw new IllegalArgumentException();
}
int old = this.packetSize;
this.packetSize = size;
if(port != null && old != size)
{
configPortWithPacketSize();
}
}
/** 获取端口名称 */
public String getName()
{
return this.portID.getName();
}
/** 处理读取到的单个报文
*
* @param bytes 包含待处理报文的字节
* @param begin 从该位置开始的字节才是报文内容起始字节
* @param length 从begin处开始length个字节才是报文的内容字节
*/
private void handleMessage(byte[] bytes, int begin, int length)
{
for(int i = handlers.size() - 1; i >= 0; i--)
{
((MessageHandler)handlers.get(i)).handleMessage(bytes, begin, length);
}
}
/** 添加报文接收侦听实现
*
* @param handler 不为null的报文接收侦听实现 */
public void addMessageHandler(MessageHandler handler)
{
this.handlers.add(handler);
}
/** 删除已经被添加的报文接收侦听实现
*
* @param handler 不为null的报文接收侦听实现 */
public void removeMessageHandler(MessageHandler handler)
{
for(int i = 0; i<handlers.size();)
{
if(handler.equals(handlers.get(i)))
{
handlers.remove(i);
}
else
{
i ++ ;
}
}
}
public void removeAllHandlers()
{
this.handlers.clear();
}
public byte[] getTerminalBytes()
{
return terminalBytes;
}
/**
*
* @return 连续两次发送的间隔时间
*/
public int getMandatoryDelay()
{
return mandatoryDelay;
}
/**
*
* @param mandatoryDelay 连续两次发送的间隔时间
*/
public void setMandatoryDelay(int mandatoryDelay)
{
this.mandatoryDelay = mandatoryDelay;
}
/**
* 设置串口上各个参数的值
* @param portParams 各个参数值的封装
* @throws IllegalArgumentException
* @throws IllegalStateException 串口已经尚未打开
*/
public void setSerialPortParams(SerialPortParam portParams)
throws IllegalArgumentException, IllegalStateException
{
checkState();
try
{
this.getPort().setSerialPortParams(
portParams.getBaudRate()
, portParams.getDataBits()
, portParams.getStopBits()
, portParams.getParity() );
}
catch (UnsupportedCommOperationException ex)
{
throw new IllegalArgumentException(ex.getMessage());
}
Object receiveMethod = portParams.getReceiveMethod();
this.delayToRead = 0;
this.terminalBytes = null;
setPacketSize(0);
if (receiveMethod.equals(SerialPortParam.METHOD_FIX_LENGTH))
{
setPacketSize(Integer.parseInt(portParams.getMethodParam()));
}
else if(receiveMethod.equals(SerialPortParam.METHOD_FIX_TERMINAL))
{
StringTokenizer st = new StringTokenizer(portParams.getMethodParam());
terminalBytes = new byte[st.countTokens()];
int i = 0;
while (st.hasMoreTokens())
{
terminalBytes[i ++] = Byte.parseByte(st.nextToken(), 10);
}
}
else if(receiveMethod.equals(SerialPortParam.METHOD_FIX_DURATION))
{
delayToRead = (Integer.parseInt(portParams.getMethodParam()));
}
}
/**
* 读取已打开串口的波特率、数据位、停止位和校验位的值,将它们存储到
* SerialPortParam实例中。
* @param portParam SerialPortParam实例
* @exception IllegalStateException 串口已经被关闭
*/
public void storeDefaultPortParam(SerialPortParam portParam)
{
checkState();
portParam.setBaudRate(port.getBaudRate());
portParam.setDataBits(port.getDataBits());
portParam.setStopBits(port.getStopBits());
portParam.setParity(port.getParity());
}
private synchronized void ensureBufferSize(int minSize)
{
if(this.rcvBuffer.length < minSize)
{
byte[] newBuffer = new byte[minSize];
System.arraycopy(this.rcvBuffer, 0, newBuffer, 0, this.rcvBuffer.length);
this.rcvBuffer = newBuffer;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -