⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialportcomm.java

📁 用于串口通讯测试的工具软件。完全使用java语言编写。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
				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 + -