Newer
Older
pgdsc / src / com / szpg / task / SetHSThresholdTask.java
package com.szpg.task;

import org.apache.log4j.Logger;

import com.szpg.db.dao.PgAcuCmdDao;
import com.szpg.db.dao.PgAcuDao;
import com.szpg.db.dao.PgDeviceDao;
import com.szpg.db.dao.PgHjsbblDao;
import com.szpg.db.dao.impl.PgAcuCmdDaoImpl;
import com.szpg.db.dao.impl.PgAcuDaoImpl;
import com.szpg.db.dao.impl.PgDeviceDaoImpl;
import com.szpg.db.dao.impl.PgHjsbblDaoImpl;
import com.szpg.db.data.PgAcu;
import com.szpg.db.data.PgAcuCmd;
import com.szpg.db.data.PgHjsbbl;
import com.szpg.plc.message.CommandResponse;
import com.szpg.plc.message.command.write.SetHSThresholdWordCommand;
import com.szpg.plc.protocol.DTProtocolInterface;
import com.szpg.plc.protocol.ProtocolFactory;
import com.szpg.plc.protocol.fins.FINSConstants;
import com.szpg.plc.server.ACUClient;
import com.szpg.plc.server.ACUClientUtil;
import com.szpg.plc.util.ByteUtil;
import com.szpg.plc.util.Bytes;
import com.szpg.util.Configure;

/**
 * 设置硫化氢报警阈值
 * 
 * @author admin
 *
 */
public class SetHSThresholdTask implements Runnable {
	
	private Logger logger = Logger.getLogger(this.getClass().getName());
	
	private String deviceCode;
	private float threshold;
	private PgHjsbblDao blDao = new PgHjsbblDaoImpl();
	
	public SetHSThresholdTask(String deviceCode, float threshold) {
		this.deviceCode = deviceCode;
		this.threshold = threshold;
	}

	@Override
	public void run() {
		// 查找ACU的信息
		PgAcuDao acuDao = new PgAcuDaoImpl();
		PgDeviceDao deviceDao = new PgDeviceDaoImpl();
		String acucode = deviceDao.findAcuCodeByCode(deviceCode);
		PgAcu acu = acuDao.findACUByCode(acucode);
		ACUClient client = ACUClientUtil.getInstance().getClients().get(acu.getAcu_host() + ":" + acu.getAcu_port());
		if (null != client) {
			// 源地址
			String sour = Configure.getProperty("sys", "LOCALHOST.NET") + 
						  Configure.getProperty("sys", "LOCALHOST.NODE") + 
						  Configure.getProperty("sys", "LOCALHOST.UNIT");
			
			// 目标地址
			String dest = client.getNet() + client.getNode() + client.getUnit();
			
			DTProtocolInterface finspi = ProtocolFactory.getDefaultDTProtocol();
			
			// 发送设置报警阈值的命令
			SetHSThresholdWordCommand setThreCmd = new SetHSThresholdWordCommand();
			setThreCmd.setThreshold(threshold);
			PgHjsbbl onBlObj = blDao.findBlByBh(deviceCode + ".Set");
			if (null != onBlObj) {
				setThreCmd.setMessageProducerId(sour);
				setThreCmd.setDestinationId(dest);
				
				// SID在new对象的时候已经生成
				
				// 内存区域——按字写
				setThreCmd.setMemoryArea(FINSConstants.MEMORY_WORK_AREA_WORD);
				
				int start = onBlObj.getKszdz();
				int end = onBlObj.getJszdz();
				
				// 开始字地址
				setThreCmd.setStartAddress(ByteUtil.binToHexString(ByteUtil.intToBins(start, 2)) + "00");
				
				// 字数
				int n = end - start + 1;
				setThreCmd.setCount(n);
				
				// 字内容
				byte[] temps = ByteUtil.intToBins(Float.floatToIntBits(threshold));
				Bytes dataByte = new Bytes();
				for (int j = n; j > 0; j--) {
					dataByte.append(new byte[] {temps[2 * (j-1)], temps[2 * (j-1) + 1]});
				}
				setThreCmd.setValue( dataByte.toBytes() );
				
				// 解析命令对象为字节数组
				byte[] content = finspi.messageToBytes(setThreCmd);
				
				// 通过socket接口发送出去
				ACUClientUtil.getInstance().sendACUCommand(client, content);
			}
			
			// 3将命令存入数据库
			PgAcuCmdDao cmdDao = new PgAcuCmdDaoImpl();
			PgAcuCmd cmd = new PgAcuCmd();
			cmd.setCmd_type(setThreCmd.getCommandType());
			cmd.setDest_acu_code(acucode);
			cmd.setTm(setThreCmd.getTime().getTime());
			cmdDao.addCmdRecord(cmd);
			
			// 4阻塞,循环查找响应消息池,找到对应的响应消息
			boolean flag = false;
			int times = 0;
			CommandResponse response = null;
			while (flag == false && times < 240) {
				response = ACUClientUtil.getInstance().responsePool.getResponse(cmd.getId());
				
				if (null != response && response.equals("") == false) {
					flag = true;
				}
				
				times++;
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO 阻塞线程被打断,需要处理异常
					// 目前的处理流程为1)记录日志;2)将命令置为超时
					logger.error("在响应池中查找命令的响应消息阻塞线程被异常打断", e);
					cmdDao.updateCmdRecordTimeout(cmd.getId());
					
					return;
				}
			}
			
			// 5若未超时,将值存入数据库
			if (null != response) {
				// 6根据命令类型的不同将监测值存入对应的数据库
				response.afterAction();
			} else {
				// 9超时,将命令的超时标志位置1
				logger.warn("命令超时" + cmd.getId());
				cmdDao.updateCmdRecordTimeout(cmd.getId());
			}
		}
	}

}