我试图与JSSC合作。 我根据这个链接构建了我的应用程序:
https://code.google.com/p/java-simple-serial-connector/wiki/jSSC_examples
我的事件处理程序如下:
static class SerialPortReader implements SerialPortEventListener {
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR()){//If data is available
try {
byte buffer[] = serialPort.readBytes();
}
catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
}
}
问题在于我总是没有将传入的数据整合在一起。 (我的消息长度为100个字节,我得到48和52个字节,2个分隔调用) - 另一方发给我不同长度的信息 - 在我工作的ICD中,有一个字段告诉我们消息的长度。 (从字节#10到字节#13) - 我读不到14个字节:
(serialPort.readBytes(14);,
解析消息长度并阅读消息的其余部分:
(serialPort.readBytes(messageLength-14);
但如果我会这样做,我将不会有一次消息(我将有2个分隔byte []并且我需要它在一个部分(byte [])而没有复制功能的工作。
使用以太网(SocketChannel)时,我们可以使用ByteBuffer读取数据。但是使用JSSC我们不能。
由于
答案 0 :(得分:2)
您不能依赖任何库一次性为您提供所有所需的内容,因为:
您必须开发自己的业务逻辑来处理数据包接收。它当然取决于你的数据包是如何定义的:它们总是长度相同,是否用相同的结尾字符分隔等等。
这是一个应该适用于您的系统的示例(请注意,您应将此作为开头,而不是完整的解决方案,例如,它不包括超时):
static class SerialPortReader implements SerialPortEventListener
{
private int m_nReceptionPosition = 0;
private boolean m_bReceptionActive = false;
private byte[] m_aReceptionBuffer = new byte[2048];
@Override
public void serialEvent(SerialPortEvent p_oEvent)
{
byte[] aReceiveBuffer = new byte[2048];
int nLength = 0;
int nByte = 0;
switch(p_oEvent.getEventType())
{
case SerialPortEvent.RXCHAR:
try
{
aReceiveBuffer = serialPort.readBytes();
for(nByte = 0;nByte < aReceiveBuffer.length;nByte++)
{
//System.out.print(String.format("%02X ",aReceiveBuffer[nByte]));
m_aReceptionBuffer[m_nReceptionPosition] = aReceiveBuffer[nByte];
// Buffer overflow protection
if(m_nReceptionPosition >= 2047)
{
// Reset for next packet
m_bReceptionActive = false;
m_nReceptionPosition = 0;
}
else if(m_bReceptionActive)
{
m_nReceptionPosition++;
// Receive at least the start of the packet including the length
if(m_nReceptionPosition >= 14)
{
nLength = (short)((short)m_aReceptionBuffer[10] & 0x000000FF);
nLength |= ((short)m_aReceptionBuffer[11] << 8) & 0x0000FF00;
nLength |= ((short)m_aReceptionBuffer[12] << 16) & 0x00FF0000;
nLength |= ((short)m_aReceptionBuffer[13] << 24) & 0xFF000000;
//nLength += ..; // Depending if the length in the packet include ALL bytes from the packet or only the content part
if(m_nReceptionPosition >= nLength)
{
// You received at least all the content
// Reset for next packet
m_bReceptionActive = false;
m_nReceptionPosition = 0;
}
}
}
// Start receiving only if this is a Start Of Header
else if(m_aReceptionBuffer[0] == '\0')
{
m_bReceptionActive = true;
m_nReceptionPosition = 1;
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
break;
default:
break;
}
}
}
答案 1 :(得分:0)
将数据写入串口后,需要刷新。检查时间并注意只有在写完另一端后才能读取的事实。读取大小只是读取系统调用的指示,不能保证。数据可能已到达并在串行端口硬件缓冲区中缓冲,但可能尚未传输到操作系统缓冲区,因此不会传输到应用程序。考虑使用scm库,它会在每次写http://www.embeddedunveiled.com/
后刷新数据答案 2 :(得分:0)
尝试一下:
将数据写入串行端口(使用serialPort.writeBytes()),如果希望得到响应,请使用以下命令:
byte[] getData() throws SerialPortException, IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b;
try {
while ((b = serialPort.readBytes(1, 100)) != null) {
baos.write(b);
// System.out.println ("Wrote: " + b.length + " bytes");
}
// System.out.println("Returning: " + Arrays.toString(baos.toByteArray()));
} catch (SerialPortTimeoutException ex) {
; //don't want to catch it, it just means there is no more data to read
}
return baos.toByteArray();
}
使用返回的字节数组执行所需的操作;就我而言,我只是将其显示以进行测试。
我发现,如果您一次读取一个字节(使用100ms超时),则它工作正常,当超时时,您已读取缓冲区中的所有数据。
来源:尝试使用jssc和ESC / POS与Epson串行打印机进行通讯。