废话不说,直接上代码
一、协议解析
//获取字节流
byte[] data = is.read(buf);
// 判断数据长度是否异常
if (length < 10) {
throw new SecsParseException(String.format("Incomplete message (message length: %d)", length));
}
//取前四个字节,得到数据长度
byte[] lengthField = new byte[4];
System.arraycopy(data, 0, lengthField, 0, 4);
long messageLength = new U4(lengthField).getValue(0);
//解析消息头
//解析sessionId
byte[] sessionIdBuf = new byte[2];
System.arraycopy(data, 4 , sessionIdBuf, 0, 2);
int sessionId = (int) ConversionUtils.bytesToUnsignedInteger(sessionIdBuf);
//获取头部字节
byte headerByte2 = data[4 + 2];
byte headerByte3 = data[4 + 3];
//解析标识类型
byte pTypeByte = data[4 + 4];
PType pType = PType.parse(pTypeByte);
if (pType != PType.SECS_II) {
throw new SecsParseException(String.format("Unsupported protocol; not SECS-II (PType: %d)", pTypeByte));
}
//解析会话类型
byte sTypeByte = data[4 + 5];
SType sType = SType.parse(sTypeByte);
if (sType == SType.UNKNOWN) {
throw new SecsParseException(String.format("Unsupported message type (SType: %02x)", sTypeByte));
}
//解析系统字节
byte[] transactionIdBuf = new byte[4];
System.arraycopy(data, 4 + 6, transactionIdBuf, 0, 4);
long transactionId = ConversionUtils.bytesToUnsignedInteger(transactionIdBuf);
if (sType == 0x00) {
//消息文本长度 = 报文消息长度 - 消息头长度
int dataLength = (int) (messageLength - SecsConstants.HEADER_LENGTH);
Data<?> text = null;
if (dataLength > 0) {
byte[] textBytes = new byte[dataLength];
System.arraycopy(data, 14, textBytes, 0, dataLength);
text = parseData(textBytes, 0);
}
int stream = headerByte2 & STREAM_MASK;//最高位表示是否回复,所以这里只取低7位的值 例:10000001 & 01111111 = 00000001
int function = headerByte3;
boolean isReply = withReply(headerByte2);
SecsMessage dataMessage = new SecsMessage(stream,function,isReply);
dataMessage.setSessionId(sessionId);
dataMessage.setTransactionId(transactionId);
dataMessage.setData(text);
//解析结束
} else {
ControlMessage controlMessage = new ControlMessage(sessionId, headerByte2, headerByte3, sType, transactionId);
//解析结束
}
二、数据内容解析
/**
* 解析数据
* @param data 字节流数据
* @param offset 起始解析位置
* @return
*/
private static Data<?> parseData(byte[] data, int offset){
if (data.length < 2) {
throw new SecsParseException("Invalid data length: " + data.length);
}
//获取格式字节
int formatByte = data[offset];
//获取数据项格式代码
int formatCode = (formatByte & 0xfc)>>2;
//获取长度字节数
int noOfLengthBytes = formatByte & 0x03;
if (noOfLengthBytes < 1 || noOfLengthBytes > LENGTH_LENGTH) {
throw new SecsParseException("Invalid number of length bytes: " + noOfLengthBytes);
}
if (data.length < noOfLengthBytes + 1) {
throw new SecsParseException("Incomplete message data");
}
//解析长度字节,获取数据总长度(单位:字节)
int length = data[offset + 1];
if (noOfLengthBytes > 1) {
length |= (data[offset + 2] << 8);
}
if (noOfLengthBytes > 2) {
length |= (data[offset + 3] << 16);
}
if (data.length < offset + 2 + length) {
throw new SecsParseException("Incomplete message data");
}
Data<?> dataItem = null;
offset += (1 + noOfLengthBytes);
switch (formatCode) {
case L.FORMAT_CODE:
dataItem = parseL(data, offset, length);
break;
case BOOLEAN.FORMAT_CODE:
dataItem = parseBoolean(data, offset, length);
break;
case B.FORMAT_CODE:
dataItem = parseB(data, offset, length);
break;
case A.FORMAT_CODE:
dataItem = parseA(data, offset, length);
break;
case I1.FORMAT_CODE:
dataItem = parseI1(data, offset, length);
break;
case I2.FORMAT_CODE:
dataItem = parseI2(data, offset, length);
break;
case I4.FORMAT_CODE:
dataItem = parseI4(data, offset, length);
break;
case I8.FORMAT_CODE:
dataItem = parseI8(data, offset, length);
break;
case U1.FORMAT_CODE:
dataItem = parseU1(data, offset, length);
break;
case U2.FORMAT_CODE:
dataItem = parseU2(data, offset, length);
break;
case U4.FORMAT_CODE:
dataItem = parseU4(data, offset, length);
break;
case U8.FORMAT_CODE:
dataItem = parseU8(data, offset, length);
break;
case F4.FORMAT_CODE:
dataItem = parseF4(data, offset, length);
break;
case F8.FORMAT_CODE:
dataItem = parseF8(data, offset, length);
break;
default:
throw new IllegalArgumentException(String.format("Invalid format code in message data: %02x", formatCode));
}
return dataItem;
}