Newer
Older
pgdsc / src / com / szpg / plc / protocol / fins / FINSDTProtocolImp.java
package com.szpg.plc.protocol.fins;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.apache.log4j.Logger;

import com.szpg.db.dao.PgAcuRdcmdDao;
import com.szpg.db.dao.impl.PgAcuRdcmdDaoImpl;
import com.szpg.db.data.PgAcuRdcmd;
import com.szpg.db.data.PgFjStat;
import com.szpg.plc.message.AppMessage;
import com.szpg.plc.message.AppMessageConstants;
import com.szpg.plc.message.UnKnownMessage;
import com.szpg.plc.message.command.LinkCommand;
import com.szpg.plc.message.command.ReadMemoryCommand;
import com.szpg.plc.message.response.LinkCommandResponse;
import com.szpg.plc.message.response.read.ReadCH4StatusCommandResponse;
import com.szpg.plc.message.response.read.ReadCH4ValueCommandResponse;
import com.szpg.plc.message.response.read.ReadCOStatusCommandResponse;
import com.szpg.plc.message.response.read.ReadCOValueCommandResponse;
import com.szpg.plc.message.response.read.ReadDSStatusCommandResponse;
import com.szpg.plc.message.response.read.ReadFjRtCommandResponse;
import com.szpg.plc.message.response.read.ReadFjStatCommandResponse;
import com.szpg.plc.message.response.read.ReadHSStatusCommandResponse;
import com.szpg.plc.message.response.read.ReadHSValueCommandResponse;
import com.szpg.plc.message.response.read.ReadO2StatusCommandResponse;
import com.szpg.plc.message.response.read.ReadO2ValueCommandResponse;
import com.szpg.plc.message.response.read.ReadWSStatusCommandResponse;
import com.szpg.plc.message.response.read.ReadWSValueCommandResponse;
import com.szpg.plc.message.response.read.ReadYWStatusCommandResponse;
import com.szpg.plc.protocol.DTProtocolInterface;
import com.szpg.plc.protocol.fins.frame.FINSByteFrame;
import com.szpg.plc.protocol.fins.frame.FINSByteFrameTool;
import com.szpg.plc.util.ByteUtil;
import com.szpg.plc.util.Bytes;

public class FINSDTProtocolImp implements DTProtocolInterface {

	private final Logger logger = Logger.getLogger(this.getClass().getName()); // 输出到message
	
	/**
	 * 从重叠消息中提取规范消息
	 */
	@Override
	public List<byte[]> extractByteMessage(byte[] byteMessage) {
		List<byte[]> bytesList = new ArrayList<byte[]>();
		int count = 0;
		
		try {
			int i = 0;
			while (i < byteMessage.length) {
				if (byteMessage[i] == FINSByteFrame.HEADER[0] && 
					byteMessage[i + 1] == FINSByteFrame.HEADER[1] &&
					byteMessage[i + 2] == FINSByteFrame.HEADER[2] &&
					byteMessage[i + 3] == FINSByteFrame.HEADER[3]) {
					
					// 匹配上FINS帧头
					int length = ByteUtil.binToInt(new byte[]{byteMessage[i + 4], byteMessage[i + 5], byteMessage[i + 6], byteMessage[i + 7]});
					if (i + length + 8 <= byteMessage.length) {
						Bytes bytes = new Bytes();
						bytes.append(byteMessage[i]).append(byteMessage[i + 1]).append(byteMessage[i + 2]).append(byteMessage[i + 3]); //FINS帧头
						bytes.append(byteMessage[i + 4]).append(byteMessage[i + 5]).append(byteMessage[i + 6]).append(byteMessage[i + 7]); //FINS长度
						
						// FINS的数据区
						for (int j = 0; j < length; j++) {
							bytes.append(byteMessage[i + 8 + j]);
						}
						
						i = i + length + 8;
						bytesList.add(bytes.toBytes());
						count++;
					} else {
						i++;
					}
				} else {
					i++;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			bytesList.clear();
			bytesList.add(byteMessage);
			return bytesList;
		}
		
		if (count == 0) {
			bytesList.add(byteMessage);
		}
		
		return bytesList;
	}

	/**
	 * 将字节数组解析为收到的消息对象
	 * 
	 * @param byte[] byteMessage
	 * @return RecievedMessage
	 */
	public AppMessage bytesToMessage(byte[] byteMessage) {

		AppMessage received = null;

		FINSByteFrame finsFrame = new FINSByteFrame(byteMessage);
		if (!finsFrame.valid) {
			received = new UnKnownMessage(byteMessage);
			received.setTime(Calendar.getInstance());
			return received;
		}

		// 根据不同字节内容,解析为各类型应用消息
		String commandStr = FINSByteFrameTool.getCommandStr(byteMessage);
		
		// 握手消息的响应
		if (commandStr.equalsIgnoreCase("00000001")) {
			received = bytesToLinkCommandResponse(finsFrame);
		}
		
		// 读写命令的响应
		if (commandStr.equalsIgnoreCase("00000002")) {
			String commandCode = FINSByteFrameTool.getFinsCommandCode(byteMessage);
			String commandType = FINSByteFrameTool.getControlSID(byteMessage); //用SID字节来代表命令类型,与APPMessageConstants中的命令类型值保持一致
			if (commandCode.equalsIgnoreCase("0101")) {
				// 读内存命令响应的解析
				
				// 1首先解析出消息的PLC端地址(即响应消息的源地址)和返回的内存内容的字数
				String dest = FINSByteFrameTool.getControlSour(byteMessage); //命令的目标地址即响应消息的源地址
//				int count = FINSByteFrameTool.getDataWithoutEndCode(byteMessage).length / 2; //1WORD=2BYTE
				
				// 2查询数据中最近的有效的读内存命令,获取其读取的参数类型
				PgAcuRdcmdDao readCmdDao = new PgAcuRdcmdDaoImpl();
				PgAcuRdcmd readCmd = readCmdDao.findLatestCmdByDestAndType(dest, commandType);
				if (null != readCmd) {
					// 3根据参数类型调用相应的方法进行解析
					switch(commandType) {
						case AppMessageConstants.CMD_TYPE_READCH4VALUE:
							received = bytesToReadCH4ValueCommandResponse(finsFrame, readCmd);
							break;
						case AppMessageConstants.CMD_TYPE_READCH4STATUS:
							received = bytesToReadCH4StatusCommandResponse(finsFrame, readCmd);
							break;
							
						case AppMessageConstants.CMD_TYPE_READWSVALUE:
							received = bytesToReadWSValueCommandResponse(finsFrame, readCmd);
							break;
						case AppMessageConstants.CMD_TYPE_READWSSTATUS:
							received = bytesToReadWSStatusCommandResponse(finsFrame, readCmd);
							break;
							
						case AppMessageConstants.CMD_TYPE_READCOVALUE:
							received = bytesToReadCOValueCommandResponse(finsFrame, readCmd);
							break;
						case AppMessageConstants.CMD_TYPE_READCOSTATUS:
							received = bytesToReadCOStatusCommandResponse(finsFrame, readCmd);
							break;
							
						case AppMessageConstants.CMD_TYPE_READO2VALUE:
							received = bytesToReadO2ValueCommandResponse(finsFrame, readCmd);
							break;
						case AppMessageConstants.CMD_TYPE_READO2STATUS:
							received = bytesToReadO2StatusCommandResponse(finsFrame, readCmd);
							break;
							
						case AppMessageConstants.CMD_TYPE_READHSVALUE:
							received = bytesToReadHSValueCommandResponse(finsFrame, readCmd);
							break;
						case AppMessageConstants.CMD_TYPE_READHSSTATUS:
							received = bytesToReadHSStatusCommandResponse(finsFrame, readCmd);
							break;
							
						case AppMessageConstants.CMD_TYPE_READYWSTATUS:
							received = bytesToReadYWStatusCommandResponse(finsFrame, readCmd);
							break;
							
						case AppMessageConstants.CMD_TYPE_READDSSTATUS:
							received = bytesToReadDSStatusCommandResponse(finsFrame, readCmd);
							break;
							
						case AppMessageConstants.CMD_TYPE_READFJSTAT:
							received = bytesToReadFjStatCommandResponse(finsFrame, readCmd);
							break;
						case AppMessageConstants.CMD_TYPE_READFJRUNTIME:
							received = bytesToReadFjRtCommandResponse(finsFrame, readCmd);
							break;
					}
					
					// 4将已响应的命令删除
					readCmdDao.deleteCmdRecord(readCmd.getId());
					
				}
			} else if (commandCode.equalsIgnoreCase("0102")) {
				// 写内存命令响应
			}
		}
		
//		
//		
//
//		default:
//			received = new UnKnownMessage(byteMessage);
//			received.setTime(Calendar.getInstance());
//		}

		return received;
	}

	

	/**
	 * 将握手响应字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToLinkCommandResponse(FINSByteFrame finsFrame) {
		LinkCommandResponse lcr = new LinkCommandResponse();

		byte[] data = finsFrame.TEXT_DATA_BODY;
		if (data.length == 8) {
			String sour = ByteUtil.binToHexString(data, 8, 16); //握手响应消息的源地址,实际上是PLC地址
			String dest = ByteUtil.binToHexString(data, 0, 8); //握手响应消息的目标地址,实际上是本机地址
		
			lcr.setMessageProducerId(sour);
			lcr.setDestinationId(dest);
			lcr.setTime(Calendar.getInstance());
			lcr.setValid(true);
		} else {
			lcr.setValid(false);
			logger.debug("握手命令响应消息数据域长度不符");
		}
		
		return lcr;
	}

	/**
	 * 将查询甲烷参数响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadCH4ValueCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadCH4ValueCommandResponse rcpcr = new ReadCH4ValueCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rcpcr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int chct = cmd.getCount_sensor(); //甲烷监测点的数量
			for (int i = 0; i < chct; i++) {
				byte[] valueByte = new byte[] { data[i*8 + 2], data[i*8 + 3], data[i*8], data[i*8 + 1] };
				byte[] thresholdByte = new byte[] { data[i*8 + 6], data[i*8 + 7], data[i*8 + 4], data[i*8 + 5] };
				
				float value = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(valueByte), 16)); //甲烷浓度值
				float threshold = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(thresholdByte), 16)); //甲烷报警阈值
				
				rcpcr.getJwnd().add(value);
				rcpcr.getJwldbjz().add(threshold);
			}
		}

		return rcpcr;
	}
	
	
	/**
	 * 将查询甲烷报警状态响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadCH4StatusCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadCH4StatusCommandResponse rcscr = new ReadCH4StatusCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rcscr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int chct = cmd.getCount_sensor(); //甲烷监测点的数量
			int bitct = cmd.getCount_bit(); //读取的位的数量,用于计算字节数
			int bytect = (bitct % 16 == 0 ? bitct / 16 : bitct / 16 + 1) * 2;
			String dataStr = "";
			for (int i = 0; i < bytect - 1; i = i + 2) {
				dataStr = ByteUtil.binToBinString(new byte[] { data[i], data[i + 1] }) + dataStr; //D15-D0顺序
			}
			
			for (int i = 0; i < chct; i++) {
				char ldBit = dataStr.charAt(dataStr.length() - 2 * i - 1);
				char bjBit = dataStr.charAt(dataStr.length() - 2 * i - 2);
				
				rcscr.getJwbj().add(bjBit == '1' ? true : false);
				rcscr.getJwldbj().add(ldBit == '1' ? true : false);
			}
		}
	
		return rcscr;
	}

	/**
	 * 将读取温湿度监测值响应字节数组转换为消息对象
	 * 
	 * @param finsFrame
	 * @return
	 */
	private AppMessage bytesToReadWSValueCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadWSValueCommandResponse rwvcr = new ReadWSValueCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rwvcr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int wsct = cmd.getCount_sensor(); //获取传感器数量
			
			int offset = cmd.getOffset(); //获取湿度变量的内存地址偏移量
			offset = offset + wsct * 2 * 2 * 2;
			
			// 解析并存储温度值
			for (int i = 0; i < wsct; i++) {
				byte[] tempValueByte = new byte[] { data[i*8 + 2], data[i*8 + 3], data[i*8], data[i*8 + 1] };
				byte[] tempThresholdByte = new byte[] { data[i*8 + 6], data[i*8 + 7], data[i*8 + 4], data[i*8 + 5] };
				
				float tempValue = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(tempValueByte), 16)); //温度监测值
				float tempThreshold = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(tempThresholdByte), 16)); //温度报警阈值
				
				rwvcr.getWd().add(tempValue);
				rwvcr.getWdbjz().add(tempThreshold);
			}
			
			// 解析并存储湿度值
			for (int i = 0; i < wsct; i++) {
				byte[] humValueByte = new byte[] { data[i*8 + 2 + offset], data[i*8 + 3 + offset], data[i*8 + offset], data[i*8 + 1 + offset] };
				byte[] humThresholdByte = new byte[] { data[i*8 + 6 + offset], data[i*8 + 7 + offset], data[i*8 + 4 + offset], data[i*8 + 5 + offset] };
				
				float humValue = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(humValueByte), 16)); //湿度监测值
				float humThreshold = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(humThresholdByte), 16)); //湿度报警阈值
				
				rwvcr.getSd().add(humValue);
				rwvcr.getSdbjz().add(humThreshold);
			}
		}

		return rwvcr;
	}
	
	
	private AppMessage bytesToReadWSStatusCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadWSStatusCommandResponse rwsscr = new ReadWSStatusCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rwsscr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int wsct = cmd.getCount_sensor(); //温湿度监测点的数量
			
			// 处理温度状态
			String tempDataStr = ByteUtil.binToBinString(new byte[] { data[0], data[1] }); //D15-D0顺序
			for (int i = 0; i < wsct; i++) {
				char ldBit = tempDataStr.charAt(tempDataStr.length() - 2 * i - 1);
				char bjBit = tempDataStr.charAt(tempDataStr.length() - 2 * i - 2);
				
				rwsscr.getWdbj().add(bjBit == '1' ? true : false);
				rwsscr.getWdldbj().add(ldBit == '1' ? true : false);
			}
			
			// 处理湿度状态
			String humDataStr = ByteUtil.binToBinString(new byte[] { data[4], data[5] }); //D15-D0顺序
			for (int i = 0; i < wsct; i++) {
				char ldBit = humDataStr.charAt(humDataStr.length() - 2 * i - 1);
				char bjBit = humDataStr.charAt(humDataStr.length() - 2 * i - 2);
				
				rwsscr.getSdbj().add(bjBit == '1' ? true : false);
				rwsscr.getSdldbj().add(ldBit == '1' ? true : false);
			}
		}
	
		return rwsscr;
	}
	
	
	/**
	 * 将查询一氧化碳参数响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadCOValueCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadCOValueCommandResponse rcovc = new ReadCOValueCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rcovc.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int chct = cmd.getCount_sensor(); //一氧化碳监测点的数量
			for (int i = 0; i < chct; i++) {
				byte[] valueByte = new byte[] { data[i*8 + 2], data[i*8 + 3], data[i*8], data[i*8 + 1] };
				byte[] thresholdByte = new byte[] { data[i*8 + 6], data[i*8 + 7], data[i*8 + 4], data[i*8 + 5] };
				
				float value = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(valueByte), 16)); //一氧化碳浓度值
				float threshold = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(thresholdByte), 16)); //一氧化碳报警阈值
				
				rcovc.getCond().add(value);
				rcovc.getColdbjz().add(threshold);
			}
		}

		return rcovc;
	}
	
	
	/**
	 * 将查询一氧化碳报警状态响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadCOStatusCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadCOStatusCommandResponse rcscr = new ReadCOStatusCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rcscr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int chct = cmd.getCount_sensor(); //一氧化碳监测点的数量
			int bitct = cmd.getCount_bit(); //读取的位的数量,用于计算字节数
			int bytect = (bitct % 16 == 0 ? bitct / 16 : bitct / 16 + 1) * 2;
			String dataStr = "";
			for (int i = 0; i < bytect - 1; i = i + 2) {
				dataStr = ByteUtil.binToBinString(new byte[] { data[i], data[i + 1] }) + dataStr; //D15-D0顺序
			}
			
			for (int i = 0; i < chct; i++) {
				char ldBit = dataStr.charAt(dataStr.length() - 2 * i - 1);
				char bjBit = dataStr.charAt(dataStr.length() - 2 * i - 2);
				
				rcscr.getCobj().add(bjBit == '1' ? true : false);
				rcscr.getColdbj().add(ldBit == '1' ? true : false);
			}
		}
	
		return rcscr;
	}
	
	
	/**
	 * 将查询氧气参数响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadO2ValueCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadO2ValueCommandResponse rovcr = new ReadO2ValueCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rovcr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int o2ct = cmd.getCount_sensor(); //氧气监测点的数量
			for (int i = 0; i < o2ct; i++) {
				byte[] valueByte = new byte[] { data[i*8 + 2], data[i*8 + 3], data[i*8], data[i*8 + 1] };
				byte[] thresholdByte = new byte[] { data[i*8 + 6], data[i*8 + 7], data[i*8 + 4], data[i*8 + 5] };
				
				float value = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(valueByte), 16)); //氧气浓度值
				float threshold = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(thresholdByte), 16)); //氧气报警阈值
				
				rovcr.getO2nd().add(value);
				rovcr.getO2ldbjz().add(threshold);
			}
		}

		return rovcr;
	}
	
	
	/**
	 * 将查询氧气报警状态响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadO2StatusCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadO2StatusCommandResponse roscr = new ReadO2StatusCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		roscr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int o2ct = cmd.getCount_sensor(); //氧气监测点的数量
			int bitct = cmd.getCount_bit(); //读取的位的数量,用于计算字节数
			int bytect = (bitct % 16 == 0 ? bitct / 16 : bitct / 16 + 1) * 2;
			String dataStr = "";
			for (int i = 0; i < bytect - 1; i = i + 2) {
				dataStr = ByteUtil.binToBinString(new byte[] { data[i], data[i + 1] }) + dataStr; //D15-D0顺序
			}
			
			for (int i = 0; i < o2ct; i++) {
				char ldBit = dataStr.charAt(dataStr.length() - 2 * i - 1);
				char bjBit = dataStr.charAt(dataStr.length() - 2 * i - 2);
				
				roscr.getO2bj().add(bjBit == '1' ? true : false);
				roscr.getO2ldbj().add(ldBit == '1' ? true : false);
			}
		}
	
		return roscr;
	}

	
	/**
	 * 将查询硫化氢参数响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadHSValueCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadHSValueCommandResponse rhvcr = new ReadHSValueCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rhvcr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int hsct = cmd.getCount_sensor(); //硫化氢监测点的数量
			for (int i = 0; i < hsct; i++) {
				byte[] valueByte = new byte[] { data[i*8 + 2], data[i*8 + 3], data[i*8], data[i*8 + 1] };
				byte[] thresholdByte = new byte[] { data[i*8 + 6], data[i*8 + 7], data[i*8 + 4], data[i*8 + 5] };
				
				float value = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(valueByte), 16)); //氧气浓度值
				float threshold = Float.intBitsToFloat(Integer.parseInt(ByteUtil.binToHexString(thresholdByte), 16)); //氧气报警阈值
				
				rhvcr.getHsnd().add(value);
				rhvcr.getHsldbjz().add(threshold);
			}
		}

		return rhvcr;
	}
	
	
	/**
	 * 将查询硫化氢报警状态响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadHSStatusCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadHSStatusCommandResponse rhscr = new ReadHSStatusCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rhscr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int hsct = cmd.getCount_sensor(); //硫化氢监测点的数量
			int bitct = cmd.getCount_bit(); //读取的位的数量,用于计算字节数
			int bytect = (bitct % 16 == 0 ? bitct / 16 : bitct / 16 + 1) * 2;
			String dataStr = "";
			for (int i = 0; i < bytect - 1; i = i + 2) {
				dataStr = ByteUtil.binToBinString(new byte[] { data[i], data[i + 1] }) + dataStr; //D15-D0顺序
			}
			for (int i = 0; i < hsct; i++) {
				char ldBit = dataStr.charAt(dataStr.length() - 2 * i - 1);
				char bjBit = dataStr.charAt(dataStr.length() - 2 * i - 2);
				
				rhscr.getHsbj().add(bjBit == '1' ? true : false);
				rhscr.getHsldbj().add(ldBit == '1' ? true : false);
			}
		}
	
		return rhscr;
	}
	
	/**
	 * 将查询爆管液位报警状态响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadYWStatusCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadYWStatusCommandResponse ryscr = new ReadYWStatusCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		ryscr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int ysct = cmd.getCount_sensor(); //爆管液位监测点的数量
			int bitct = cmd.getCount_bit(); //读取的位的数量,用于计算字节数
			int bytect = (bitct % 16 == 0 ? bitct / 16 : bitct / 16 + 1) * 2;
			String dataStr = "";
			for (int i = 0; i < bytect - 1; i = i + 2) {
				dataStr = ByteUtil.binToBinString(new byte[] { data[i], data[i + 1] }) + dataStr; //D15-D0顺序
			}
			for (int i = 0; i < ysct; i++) {
				char bjBit = dataStr.charAt(dataStr.length() - i - 1);
				
				ryscr.getYwbj().add(bjBit == '1' ? true : false);
			}
		}
	
		return ryscr;
	}
	
	/**
	 * 将查询对射报警状态响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadDSStatusCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadDSStatusCommandResponse rdscr = new ReadDSStatusCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rdscr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int dsct = cmd.getCount_sensor(); //对射监测点的数量
			int bitct = cmd.getCount_bit(); //读取的位的数量,用于计算字节数
			int bytect = (bitct % 16 == 0 ? bitct / 16 : bitct / 16 + 1) * 2;
			String dataStr = "";
			for (int i = 0; i < bytect - 1; i = i + 2) {
				dataStr = ByteUtil.binToBinString(new byte[] { data[i], data[i + 1] }) + dataStr; //D15-D0顺序
			}
			
			for (int i = 0; i < dsct; i++) {
				char bjBit = dataStr.charAt(dataStr.length() - i * 3 - 1);
				
				rdscr.getDsbj().add(bjBit == '1' ? true : false);
			}
		}
	
		return rdscr;
	}
	
	
	/**
	 * 将查询风机运行状态响应消息字节数组转换为消息对象
	 * 
	 * @param byteMessage
	 * @return
	 */
	private AppMessage bytesToReadFjStatCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadFjStatCommandResponse rfscr = new ReadFjStatCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rfscr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int fjct = cmd.getCount_sensor(); //风机的数量
			int bitct = cmd.getCount_bit(); //读取的位的数量,用于计算字节数
			int bytect = (bitct % 16 == 0 ? bitct / 16 : bitct / 16 + 1) * 2;
			String dataStr = "";
			for (int i = 0; i < bytect - 1; i = i + 2) {
				dataStr = ByteUtil.binToBinString(new byte[] { data[i], data[i + 1] }) + dataStr; //D15-D0顺序
			}
			
			for (int i = 0; i < fjct; i++) {
				char amBit = dataStr.charAt(dataStr.length() - i * 8 - 1);
				char runBit = dataStr.charAt(dataStr.length() - i * 8 - 2);
				char fltBit = dataStr.charAt(dataStr.length() - i * 8 - 3);
				char enBit = dataStr.charAt(dataStr.length() - i * 8 - 4);
				char noBit = dataStr.charAt(dataStr.length() - i * 8 - 5);
				char routBit = dataStr.charAt(dataStr.length() - i * 8 - 8);
				
				PgFjStat fjzt = new PgFjStat();
				fjzt.setAm(amBit == '1' ? true : false);
				fjzt.setRun(runBit == '1' ? true : false);
				fjzt.setFlt(fltBit == '1' ? true : false);
				fjzt.setEn(enBit == '1' ? true : false);
				fjzt.setNo(noBit == '1' ? true : false);
				fjzt.setRout(routBit == '1' ? true : false);
				
				rfscr.getFjzt().add(fjzt);
			}
		}
	
		return rfscr;
	}
	
	
	/**
	 * 将读取风机运行时长响应字节数组转换为消息对象
	 * 
	 * @param finsFrame
	 * @return
	 */
	private AppMessage bytesToReadFjRtCommandResponse(FINSByteFrame finsFrame, PgAcuRdcmd cmd) {
		ReadFjRtCommandResponse rfrcr = new ReadFjRtCommandResponse();
		
		byte[] body = finsFrame.TEXT_DATA_BODY;
		rfrcr.setMessageProducerId(FINSByteFrameTool.getControlDest(finsFrame));
		if (body[2] == 0x00 && body[3] == 0x00) {
			// 正常返回
			byte[] data = FINSByteFrameTool.getDataWithoutEndCode(finsFrame); //获取返回的内存
			int fjct = cmd.getCount_sensor(); //获取风机数量
			
			int offset = cmd.getOffset(); //获取风机小时数变量的内存地址偏移量
			offset = offset + fjct * 2;
			
			// 解析并存储风机运行时长秒数
			for (int i = 0; i < fjct; i++) {
				byte[] secondByte = new byte[] { data[i*2], data[i*2 + 1] };
				
				int second = ByteUtil.binToInt(secondByte); // 运行时长的秒数
				
				rfrcr.getFjscs().add(second);
			}
			
			// 解析并存储风机运行时长小时数
			for (int i = 0; i < fjct; i++) {
				byte[] hourByte = new byte[] { data[i*4 + 2 + offset], data[i*4 + 3 + offset], data[i*4 + offset], data[i*4 + 1 + offset] };
				
				int hourValue = ByteUtil.binToInt(hourByte); //运行时长的小时数
				
				rfrcr.getFjsch().add(hourValue);
			}
		}

		return rfrcr;
	}

	/**
	 * 将消息对象解析为字节数组
	 * 
	 * @param SentMessage message
	 * @return byte[]
	 */
	public byte[] messageToBytes(AppMessage message) {
		byte[] frame = null;

		// 握手命令
		if (message instanceof LinkCommand) {
			frame = LinkCommandToBytes((LinkCommand) message);
		}
		
		// 读内存命令
		if (message instanceof ReadMemoryCommand) {
			frame = readMemoryCommandToBytes((ReadMemoryCommand) message);
		}
//		
//		// 写内存命令
//		if (message instanceof QueryRealTimeValueCommand) {
//			frame = queryRealTimeValueCommandToBytes((QueryRealTimeValueCommand) message);
//		}
		
		return frame;
	}



	/**
	 * 将握手命令转换为字节数组
	 * 
	 * @param hmr
	 * @return
	 */
	private byte[] LinkCommandToBytes(LinkCommand link) {
		FINSByteFrame finsFrame = new FINSByteFrame(link.getMessageProducerId());

		return finsFrame.toBytes();
	}
	
	/**
	 * 将读取PLC内存命令转换为字节数组
	 * 
	 * @param message
	 * @return
	 */
	private byte[] readMemoryCommandToBytes(ReadMemoryCommand message) {
		byte[] start = ByteUtil.hexStringToBytes(message.getStartAddress(), 3);
		
		FINSByteFrame finsFrame = new FINSByteFrame(message.getDestinationId(), 
													message.getMessageProducerId(), 
													message.getCommandType(),
													message.getMemoryArea(), 
													start, 
													message.getCountWord());
		
		return finsFrame.toBytes();
	}
	
	/**
	 * 将读取甲烷监测值命令转换为字节数组
	 * @param message
	 * @return
	 */
//	private byte[] ReadCH4ValueCommandToBytes(ReadCH4ValueCommand message) {
//		byte[] start = ByteUtil.hexStringToBytes(message.getStartAddress(), 3);
//		
//		FINSByteFrame finsFrame = new FINSByteFrame(message.getDestinationId(), 
//													message.getMessageProducerId(), 
//													message.getMemoryArea(), 
//													start, 
//													message.getCountWord());
//		
//		return finsFrame.toBytes();
//	}

	/**
	 * 将读取甲烷报警状态命令转换为字节数组
	 * @param message
	 * @return
	 */
//	private byte[] ReadCH4StatusCommandToBytes(ReadCH4StatusCommand message) {
//		byte[] start = ByteUtil.hexStringToBytes(message.getStartAddress(), 3);
//		
//		FINSByteFrame finsFrame = new FINSByteFrame(message.getDestinationId(), 
//													message.getMessageProducerId(), 
//													message.getMemoryArea(), 
//													start, 
//													message.getCountWord());
//
//		return finsFrame.toBytes();
//	}
	
	/**
	 * 将读取温湿度监测值命令转换为字节数组
	 * 
	 * @param message
	 * @return
	 */
//	private byte[] ReadWSValueCommandToBytes(ReadWSValueCommand message) {
//		byte[] start = ByteUtil.hexStringToBytes(message.getStartAddress(), 3);
//		
//		FINSByteFrame finsFrame = new FINSByteFrame(message.getDestinationId(), 
//													message.getMessageProducerId(), 
//													message.getMemoryArea(), 
//													start, 
//													message.getCountWord());
//		
//		return finsFrame.toBytes();
//	}
	
	/**
	 * 将读取温湿度报警状态命令转换为字节数组
	 * 
	 * @param message
	 * @return
	 */
//	private byte[] ReadWSStatusCommandToBytes(ReadWSStatusCommand message) {
//		byte[] start = ByteUtil.hexStringToBytes(message.getStartAddress(), 3);
//		
//		FINSByteFrame finsFrame = new FINSByteFrame(message.getDestinationId(), 
//													message.getMessageProducerId(), 
//													message.getMemoryArea(), 
//													start, 
//													message.getCountWord());
//
//		return finsFrame.toBytes();
//	}

}