package com.szpg.plc.protocol.fins.frame; import com.szpg.plc.protocol.fins.FINSConstants; import com.szpg.plc.util.ByteUtil; import com.szpg.plc.util.Bytes; public class FINSByteFrameTool { /** * 获取数据帧的长度字 * 位于整个消息帧的5-8字节 * * @param finsFrame * @return */ public static int getFrameLength(byte[] finsFrame) { if (finsFrame.length < 8) { return 0; } byte[] lengthByte = new byte[] {finsFrame[4], finsFrame[5], finsFrame[6], finsFrame[7]}; return ByteUtil.binToInt(lengthByte); } /** * 获取帧的功能码 * 位于整个消息帧的9-12字节 * * @param finsFrame * @return */ public static String getCommandStr(byte[] finsFrame) { if (finsFrame.length < 12) { return ""; } return ByteUtil.binToHexString(finsFrame, 16, 24); } /** * 获取帧的错误代码 * 位于整个消息帧的13-16字节 * * @param finsFrame * @return */ public static String getErrorCodeStr(byte[] finsFrame) { if (finsFrame.length < 16) { return ""; } return ByteUtil.binToHexString(finsFrame, 24, 32); } /** * 获取帧的TEXT域数据 * 代表用户数据 * * @param finsFrame * @return */ public static String getTextStr(byte[] finsFrame) { return ByteUtil.binToHexString(getText(finsFrame)); } /** * 获取帧的TEXT域数据 * * @param finsFrame * @return */ public static byte[] getText(byte[] finsFrame) { if (finsFrame.length < 16) { return null; } Bytes textBytes = new Bytes(); for (int i = 16; i < finsFrame.length; i++) { textBytes.append(finsFrame[i]); } return textBytes.toBytes(); } /** * 获取ICF字节 * 位于TEXT区的第一个字节 * 如果是握手响应消息则没有该字节 * * @param finsFrame * @return */ public static String getControlICF(byte[] finsFrame) { byte[] text = getText(finsFrame); if (null != text && text.length > 10) return ByteUtil.binToHexString(new byte[] {text[0]}); else return ""; } /** * 获取目标地址字符串 * 目标地址=目标网络号+目标节点号+目标单元号 * * @param finsFrame * @return */ public static String getControlDest(byte[] finsFrame) { byte[] text = getText(finsFrame); if (null != text && text.length > 10) return ByteUtil.binToHexString(new byte[] {text[3], text[4], text[5]}); else return ""; } /** * 获取源地址字符串 * 源地址=源网络号+源节点号+源单元号 * * @param finsFrame * @return */ public static String getControlSour(byte[] finsFrame) { byte[] text = getText(finsFrame); if (null != text && text.length > 10) return ByteUtil.binToHexString(new byte[] {text[6], text[7], text[7]}); else return ""; } /** * 获取命令代码 * 0x0101=读取内存,0x0102=写内存 * * @param finsFrame * @return */ public static String getFinsCommandCode(byte[] finsFrame) { byte[] text = getText(finsFrame); if (null != text && text.length >= 10) return ByteUtil.binToHexString(new byte[] {text[10], text[11]}); else return ""; } /** * 获取读取的数据内容 * 不包括END CODE * * @param finsFrame * @return */ public static byte[] getDataWithoutEndCode(byte[] finsFrame) { byte[] text = getText(finsFrame); if (null != text && text.length > 22) { Bytes dataBody = new Bytes(); for (int i = 23; i < text.length; i++) { dataBody.append(text[i]); } return dataBody.toBytes(); } else { return null; } } /** * 获取包含END CODE在内的用户数据域 * * @param finsFrame * @return */ public static byte[] getDataWithEndCode(byte[] finsFrame) { byte[] text = getText(finsFrame); if (null != text && text.length > 20) { Bytes dataBody = new Bytes(); for (int i = 23; i < text.length; i++) { dataBody.append(text[i]); } return dataBody.toBytes(); } else { return null; } } /** * 生成控制域10个字节的内容 * * @param dest 目标地址:网络号+节点号+单元号 * @param sour 源地址:网络号+节点号+单元号 * @return */ public static byte[] buildFrameControl(String dest, String sour) { byte[] control = new byte[10]; // 命令类型位固定为1,需要响应标志位固定为0,表示从上位机发送给PLC端的消息,需要PLC响应 control[0] = (byte) 0x80; // ICF字节 control[1] = FINSConstants.RSV; // RSV字节 control[2] = FINSConstants.GCT; // GCT字节 byte[] destByte = ByteUtil.hexStringToBytes(dest); byte[] sourByte = ByteUtil.hexStringToBytes(sour); control[3] = destByte[0]; //目标网络号 control[4] = destByte[1]; //目标节点号 control[5] = destByte[2]; //目标单元号 control[6] = sourByte[0]; //源网络号 control[7] = sourByte[1]; //源节点号 control[8] = sourByte[2]; //源单元号 control[9] = FINSConstants.SID; // SID字节 return control; } /** * 生成地址域 * * @param address * @return */ public static byte[] buildFrameAddress(String address) { if (address.length() != 10) return null; Bytes addressBytes = new Bytes(); byte[] addvcdBytes = ByteUtil.bcdStringToBytes(address.substring(0, 6)); byte[] dtuidBytes = ByteUtil.hexStringToBytes(address.substring(6, 10)); addressBytes.append(addvcdBytes).append(dtuidBytes[1]).append(dtuidBytes[0]); return addressBytes.toBytes(); } }