Java採用Netty實現基於DTU的TCP服務器 + 多端口 + 多協議

前一篇文章我以經實現了基於java原生的socket來實現TCP服務器,並可以解析數據,可以說是一個比較簡單的結構。後來我通過研究Netty發出,Netty是一個很好的框架,比較穩定。

1,還是那個拓撲結構

2.後臺流程圖

3.代碼

1)MainPrl.java

main函數實現了設備動態加載,可以通過配置文件很靈活的設置設備的增減。

package qx.drc.main;

import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import qx.drc.ser.DataRecvServer;
import qx.drc.utils.CommTool;
import qx.drc.utils.MyPath;

public class MainPrl {
	private static final Logger logger = LoggerFactory.getLogger(MainPrl.class);
	private static DataReceiveConfig cfg=DataReceiveConfig.getInstance();
	
	public static void main(String[] args) {
		// TODO 自動生成的方法存根
		
		List<DrcProInfo> list=cfg.listDrcPros;		
		for (DrcProInfo drcProInfo : list) {			 
		    try {	   
		    	logger.info("初始化程序:"+drcProInfo.getParseDataName()); 
		    	CommTool.printInfo("初始化程序:"+drcProInfo.getParseDataName());
		    	
		    	CommTool.printInfo( drcProInfo.getJarPath());
		    	
		    	URL url=new URL("file:"+ drcProInfo.getJarPath());
		        URLClassLoader myClassLoader=new URLClassLoader(new URL[]{url},
		        		Thread.currentThread().getContextClassLoader());
				Class myClass=null;
		        ParseData parseData=null;
				try {
					myClass = myClassLoader.loadClass(drcProInfo.getJarClassFullName());
				    parseData=(ParseData)myClass.newInstance();
				    parseData.setDrcProInfo(drcProInfo);				 
					 
				} catch (ClassNotFoundException e) {					
					e.printStackTrace();
					continue;
				}
				catch (InstantiationException e) {					
					e.printStackTrace();
					continue;
				} catch (IllegalAccessException e) {					
					e.printStackTrace();
					continue;
				}  
				DataRecvServer server = new DataRecvServer(drcProInfo.getPort(),
						drcProInfo.getParseDataName(),parseData);
				try {
					server.start();
				} catch (Exception e) {
					// TODO 自動生成的 catch 塊
					e.printStackTrace();
				}
				myClassLoader.close();
			} catch (IOException e) {			
				logger.error(e.getMessage()); 
				e.printStackTrace();
			}  
		}

	}

}

 

2) DataRecvServer.java

DataRecvServer類主要實現了新建一個服務器,並初始化服務器設置

import java.io.IOException;

import javax.xml.stream.events.StartDocument;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import qx.drc.main.ParseData;


public class DataRecvServer {
	private static final Logger logger = LoggerFactory.getLogger(DataRecvServer.class);
	private int port; //接收數據端口
	private String proName; // 接收數據名稱
	private ParseData parseData; //解析數據對象
	
	EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();
	
	public DataRecvServer(int port,String proName,ParseData parseData){
		this.port=port;
		this.proName=proName;
		this.parseData=parseData;
	}
	
    public void start() throws Exception{ 
    	EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        
        //創建ServerBootstrap實例
        ServerBootstrap serverBootstrap=new ServerBootstrap();
        //初始化ServerBootstrap的線程組
        serverBootstrap.group(bossGroup,workerGroup);
        //設置將要被實例化的ServerChannel類
        serverBootstrap.channel(NioServerSocketChannel.class);
        //serverBootstrap.handler(new LoggingHandler(LogLevel.ERROR));
        //在ServerChannelInitializer中初始化ChannelPipeline責任鏈,並添加到serverBootstrap中
        serverBootstrap.childHandler(new ServerChannelInitializer(this.parseData));
        //標識當服務器請求處理線程全滿時,用於臨時存放已完成三次握手的請求的隊列的最大長度
        serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024);
        // 是否啓用心跳保活機機制
        serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);    
        //綁定端口後,開啓監聽
        /*ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
        if(channelFuture.isSuccess()){
            System.out.println("TCP服務啓動 成功---------------");
        }*/
        
        ChannelFuture f = serverBootstrap.bind(port);
        f.addListener(future -> {
            if (future.isSuccess()) {
                System.out.printf("%s 開啓端口 %s 成功\n",proName, port);
            } else {
                System.out.printf("%s 開啓端口 %s 失敗\n", proName,port);
            }
        });
    	
    }

	public void setPort(int port) {
		this.port = port;
	}
	
	public void setProName(String proName) {
		this.proName = proName;
	} 
	
	public void setParseData(ParseData parseData) {
		this.parseData = parseData;
	}


}

 

4)ServerChannelInitializer.java

ServerChannelInitializer類主要實現了,初化服務器通道的,即加載編碼器,解碼器及數據解析

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
import qx.drc.main.ParseData;


public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
	private static final Logger logger = LoggerFactory.getLogger(ServerChannelInitializer.class);
    static final EventExecutorGroup group = new DefaultEventExecutorGroup(2);
    private ParseData parseData;
     
    public ServerChannelInitializer(ParseData parseData) throws InterruptedException {
    	this.parseData = parseData;
    }
    
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {    
        ChannelPipeline pipeline = socketChannel.pipeline();
        //IdleStateHandler心跳機制,如果超時觸發Handle中userEventTrigger()方法
        pipeline.addLast("idleStateHandler",new IdleStateHandler(15, 0, 0, TimeUnit.MINUTES));

        pipeline.addLast(new ByteArrayEncoder());

        pipeline.addLast(new DataDecoder(this.parseData));
        pipeline.addLast(new DataServerHandler(this.parseData));
    }
}

5)DataDecoder.java

DataDecoder是一個公共解碼類,解碼方式傳遞接口的方式結出。


import java.util.List;

import org.apache.log4j.lf5.PassingLogRecordFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import qx.drc.main.ParseData;
import qx.drc.utils.ByteUtils;
import qx.drc.utils.CommTool;
/**
 * 解碼器
 * @author 70910
 *
 */
public class DataDecoder extends ByteToMessageDecoder{
	protected final Logger log = LoggerFactory.getLogger(getClass());
	private ParseData parseData;
	
	public DataDecoder(ParseData parseData) {
		this.parseData = parseData;
	}

	@Override
	protected void decode(ChannelHandlerContext arg0, ByteBuf in, List<Object> list) throws Exception {
		// TODO 自動生成的方法存根
		//System.err.println(parseData.getDrcProInfo().getParseDataName() + "--------解碼器正在解碼----------");
		try {
			in.retain();
			parseData.decoder(in,list);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	@Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }
}

6)DataServerHandler.java

公共解析類,通過傳遞的接口類,實現數據解析與存儲


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import qx.drc.main.ParseData;
import qx.drc.utils.ByteUtils;
import qx.drc.utils.CommTool;

public class DataServerHandler extends ChannelInboundHandlerAdapter{
	protected final Logger log = LoggerFactory.getLogger(getClass());
	private ParseData parseData;
	
	public DataServerHandler(ParseData parseData) {
		this.parseData = parseData;
	}

	/**
     * 當我們通道進行激活的時候 觸發的監聽方法
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

        System.err.println(parseData.getDrcProInfo().getParseDataName() + "--------通道激活------------");
    }

    /**
     * 當我們的通道里有數據進行讀取的時候 觸發的監聽方法
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx /*NETTY服務上下文*/, Object msg /*實際的傳輸數據*/) throws Exception {
    	if(msg instanceof byte[]){
    		byte[] bytes = (byte[]) msg;
            	CommTool.printInfo(parseData.getDrcProInfo().getParseDataName()+",接收到數據 " + bytes.length + " bytes");	
        		
                //解析 ,需要判定是否是心跳包               
                if(!parseData.parse(bytes)){
                	log.info(parseData.getDrcProInfo().getParseDataName()+",接收數據解析失敗");
                	CommTool.printInfo(parseData.getDrcProInfo().getParseDataName()+",數據解析失敗");
                	return;
                }
                
              //存儲	
                if(!parseData.save()){
                	log.info(parseData.getDrcProInfo().getParseDataName()+",數據存儲失敗");
                	CommTool.printInfo(parseData.getDrcProInfo().getParseDataName()+",數據存儲失敗");
                	return;
                } 
              
                if(!parseData.save2Txt()){
                	log.info(parseData.getDrcProInfo().getParseDataName()+",數據存儲到TXT失敗");
                	CommTool.printInfo(parseData.getDrcProInfo().getParseDataName()+",數據存儲到TXT失敗");
                	return;
                } 
                
            	CommTool.printInfo(parseData.getDrcProInfo().getParseDataName()+",數據解析存儲成功");
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.err.println(parseData.getDrcProInfo().getParseDataName() + "--------數據讀取完畢----------");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        System.err.println(parseData.getDrcProInfo().getParseDataName() + "--------數據讀異常----------: ");
        cause.printStackTrace();
        ctx.close();
    }
}

7) ParseData.java

解碼,解析接口類,通過繼承可以實現具體的解碼和解析功能

import java.util.Date;
import java.util.List;

import io.netty.buffer.ByteBuf;

/**
 * 解析接口 
 * @author yangze
 *
 */
public interface ParseData {
	//解析
	boolean parse(byte[] bytes);
	//解碼
	boolean decoder(ByteBuf in,List<Object> list);
	//保存
	boolean save();  
	//保存文本
	public boolean save2Txt();
	//設置項目信息
	void setDrcProInfo(DrcProInfo drcProInfo);  
	//獲取項目信息
	DrcProInfo getDrcProInfo();
	//是否是心跳包
	boolean isHeartPack();
	//獲取最後心跳時間
	Date getLastHeartPackDate();
}

8)實現解碼與解析類,關注decoder與parse兩個方法即可

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import io.netty.buffer.ByteBuf;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;

import qx.drc.main.DeviceInfo;
import qx.drc.main.DrcProInfo;
import qx.drc.main.ParamInfo;
import qx.drc.main.ParseData;
import qx.drc.utils.ByteUtils;
import qx.drc.utils.CRC16_Modbus;
import qx.drc.utils.CommTool;
import qx.drc.utils.DateUtils;
import qx.drc.utils.MyPath;

/**
 * 解析負氧離子數據
 * @author yangze
 * 2019-08-21
 *
 */
public class AnionSensorDataParse implements ParseData {
	private static Logger logger = Logger.getLogger(AnionSensorDataParse.class); 
	public DrcProInfo drcProInfo;	
	private int deviAddr;	//設備地址
	private int funcCode;	//功能碼
	private int dataLength; //數據長度
	private int anionData; 
	private String typeOfPk;
	private byte[] srcData;
	
	private DeviceInfo deviceInfo = new DeviceInfo();
	private Map<String, ParamInfo> name2ParamInfoMap= new HashMap<String, ParamInfo>();
	
	private static Connection conn = null;
	private Date lastDataTime = new Date();
	private boolean isHeartPk = false;
	
    public AnionSensorDataParse(){
    	
    }
    
    // 初始化數據庫
 	private boolean iniDB() {
 		if (conn != null){
 			try {
 				if(conn.isClosed()){
 					conn = DriverManager.getConnection(drcProInfo.getDbConnUrl());									
 				}
 				return true;
 			} catch (SQLException ex) {
 				logger.error(drcProInfo.getParseDataName()+","+ex.getMessage());
 	         	CommTool.printInfo(drcProInfo.getParseDataName()+",數據庫鏈接失敗");
 				ex.printStackTrace();
 			}					
 		}
 		
 		try {
 			Class.forName("com.mysql.jdbc.Driver").newInstance();
 		} catch (Exception ex) {
 			logger.error(drcProInfo.getParseDataName()+","+ex.getMessage());
          	CommTool.printInfo(drcProInfo.getParseDataName()+",數據庫驅動載入失敗");
 			return false;
 		}
 		try {
 			conn = DriverManager.getConnection(drcProInfo.getDbConnUrl());
 			return true;
 		} catch (SQLException ex) {
 			logger.error(drcProInfo.getParseDataName()+","+ex.getMessage());
 			CommTool.printInfo(drcProInfo.getParseDataName()+","+ex.toString());
 			return false;
 		}
 	}
	
 	
 	/**
 	 * 獲取設備信息
 	 * @return
 	 */
 	private boolean getDeviceInfo() {
 		if(iniDB()){
 			
 			try{
 				Statement stmt = conn.createStatement(); //創建Statement對象

 	            String sql = "select devi_id,devi_code,devi_name from device_info where devi_code='"+ drcProInfo.getDeviceCode()+"'" ;	     
 	            
 	            ResultSet rs = stmt.executeQuery(sql);//創建數據對象
 	            ResultSetMetaData rsmd = rs.getMetaData() ;
 	            int columnCount = rsmd.getColumnCount();
 	            if(columnCount <= 0) return false;
 	            
 	            while (rs.next()){
 	            	deviceInfo.setDeviId(rs.getString(1));
 	            	deviceInfo.setDeviCode(rs.getString(2));
 	            	deviceInfo.setDeviName(rs.getString(3));
 	            }
 	            rs.close();
 	            stmt.close();
 	            return true;
 			}catch(Exception e){
 				logger.error(drcProInfo.getParseDataName()+",error:"+e.getMessage());
			    CommTool.printInfo(drcProInfo.getParseDataName()+",獲取設備信息錯誤");
				return false;
	        }
		}
		else
			return false;  
 	}
 	
 	/**
 	 * 獲取設備監測指標信息
 	 * @return
 	 */
 	private boolean getDeviceParamsInfo() {
 		if(iniDB()){
 			try{
 				Statement stmt = conn.createStatement(); //創建Statement對象

 	           String sql = "SELECT p.para_id,p.para_name,p.para_unit FROM devi_para_rel d " + 
 	   				"LEFT JOIN param_info p ON p.para_id = d.para_id " + 
 	   				"where d.devi_id='" + deviceInfo.getDeviId() + "'";
 	           
 	            ResultSet rs = stmt.executeQuery(sql);//創建數據對象
 	            ResultSetMetaData rsmd = rs.getMetaData() ;
	            int columnCount = rsmd.getColumnCount();
	            if(columnCount <= 0) return false;
	            
 	            while (rs.next()){
 	            	ParamInfo paramInfo = new ParamInfo();
 	            	paramInfo.setParaId(rs.getString(1));
 	            	paramInfo.setParaName(rs.getString(2));
 	            	paramInfo.setParaUnit(rs.getString(3));
 	            	name2ParamInfoMap.put(paramInfo.getParaName(), paramInfo);
 	            }
 	            rs.close();
 	            stmt.close();
 	            return true;
 			}catch(Exception e){
 				logger.error(drcProInfo.getParseDataName()+",error:"+e.getMessage());
			    CommTool.printInfo(drcProInfo.getParseDataName()+",獲取設備信息錯誤");
				return false;
	        }
		}
		else
			return false;  
 	}
 	
 	 @Override
 	public boolean decoder(ByteBuf in,List<Object> list) {
 		if(in.readableBytes() < 9) {
 			//數據包長度不夠,繼續接收再處理
 			System.err.println(drcProInfo.getParseDataName() + "-----------數據包不完整,繼續讀取");
			return false; 
		}
 		else{
 			int headIndex = in.readerIndex();
 			while(in.readableBytes() > 1) {
 				//讀兩個字節
 				byte[] headArray = new byte[2];
 				in.readBytes(headArray);
 				//重置讀取位置
 	            if(headArray[0] == 0x01 && headArray[1] == 0x03) {
 	            	//如果爲頭,跳出循環
 	            	break;
 	            }
 	           headIndex += 2;
 			}
 			
 			in.readerIndex(headIndex);
 			if(in.readableBytes() < 9) {
 				//餘下的數據是否足夠一個包
 				System.err.println(drcProInfo.getParseDataName() + "-----------餘下的數據不足夠一個包,繼續接收......");
 				return false;
 			}
 			else {
 				byte[] data = new byte[9];
 				in.readBytes(data);
 	            list.add(data);
 	            System.err.println(drcProInfo.getParseDataName() + "------------解碼器解碼成功");
 			}
 			
 		}
 	
 		 return true;
 	}
    @Override
    //01 03 04 A1 20 00 07 99 C7
    //報文解釋說明:“01”設備地址;“03”讀功能碼;“04”數據長度;“A1 20 00 07”爲寄存器值;“99 C7”校驗碼。計算負氧離子: 0x0007A120=500000個
    public boolean parse(byte[] data){
    	isHeartPk = false;
    	srcData = Arrays.copyOfRange(data, 0, 9);
    	String preStr=drcProInfo.getParseDataName();
		int indexNow=0;
		//設備地址
		byte[] arr= Arrays.copyOfRange(srcData, indexNow, indexNow+1);
		deviAddr=bytes2Byte255(arr[0]);	
		indexNow+=1;
		
		if(deviAddr != 0x01)
		{
			logger.error(preStr+",數據包:包頭錯誤");
			CommTool.printInfo(preStr+"數據包:包頭錯誤");
			return false;			
		}
		//功能碼
		arr=Arrays.copyOfRange(srcData, indexNow,indexNow+ 1);	    	
		funcCode=bytes2Byte255(arr[0]);
		indexNow+=1;
		
		//System.out.println("功能碼:"+  CommTool.getHexString(arr));
		
		if(funcCode == 0x03)
		{
			typeOfPk = "讀取負氧離子個數";
			arr=Arrays.copyOfRange(srcData, indexNow,indexNow+ 1);	    	
			dataLength=bytes2Byte255(arr[0]);		
	        indexNow++;
	        
	        byte[] anionDataArr =  new byte[4];
	        anionDataArr[1] = (Arrays.copyOfRange(srcData, indexNow, indexNow+1))[0];
	        indexNow++;
	        anionDataArr[0] = (Arrays.copyOfRange(srcData, indexNow, indexNow+1))[0];
	        indexNow++;
	        anionDataArr[3] = (Arrays.copyOfRange(srcData, indexNow, indexNow+1))[0];
	        indexNow++;
	        anionDataArr[2] = (Arrays.copyOfRange(srcData, indexNow, indexNow+1))[0];
	        indexNow++;
	        anionData = ByteUtils.getInt(anionDataArr);
	        
	        //System.out.println("負氧離子16進制:" +  CommTool.getHexString(CommTool.intToByteArray(anionData)));
	        //System.out.println("負氧離子個數:" + anionData);
	               
	        if(!crc16Validate(srcData, 7)){
				byte[] arr_temp=Arrays.copyOfRange(srcData,0,dataLength+2);
				String str=CommTool.getHexString(arr_temp); 
	        	logger.error(preStr+"CRC16校驗錯誤.["+str+"]");
				CommTool.printInfo(preStr+"CRC16校驗錯誤");				
				return false;
			}
	        indexNow+=2;
	        
	        //打印輸出
	        if(drcProInfo.isOutputConsole()){
		        System.out.println("**************************");
		        CommTool.printHexString(srcData);
		        System.out.println(" package size (byte): "+String.valueOf(indexNow));
		        System.out.println(" package type: "+typeOfPk);
		        byte[] funcCodeByte = {CommTool.intToByteArray(funcCode)[0]};
		        System.out.println(" function code: "+CommTool.getHexString(funcCodeByte));
		        byte[] deviAddrByte = {CommTool.intToByteArray(deviAddr)[0]};
		        System.out.println(" address of anion sensor: " + CommTool.getHexString(deviAddrByte));
		        System.out.println(" data size: "+ dataLength);
		        System.out.println(" anion num: "+ anionData);
		        System.out.println("**************************");
	        }
	        return true;
		}
		else
		{
		   CommTool.printInfo(preStr+",數據包類型不正確");
		   logger.error(preStr+",數據包類型不正確");
		   return false;
		}
	}
    @Override
 	public boolean isHeartPack() {
 		
 		return this.isHeartPk;
 	}
 	
 	@Override
    public Date getLastHeartPackDate() {
    	return this.lastDataTime;
    }
 	
    private boolean crc16Validate(byte[] byteArr,int datalength){
		byte[] dataArr = new byte[datalength];
		byte[] crc16Arr=new byte[2];
		System.arraycopy(byteArr, 0, dataArr, 0, datalength);
		System.arraycopy(byteArr, datalength, crc16Arr, 0, 2);
		int crc16=CRC16_Modbus.calcCrc16(dataArr,0,dataArr.length);
		int crc16_=(int)ByteUtils.getInt(new byte[]{crc16Arr[0],crc16Arr[1],0,0});
		if(crc16 == crc16_) return true;
		else return false;
	}
	
	private int bytes2Byte255(byte b) {  
	     int num = 0;  	     
	     num |= (b & 0xff);  	      
	     return num;  
	} 
	
	@Override
	public boolean save2Txt() {
		if(drcProInfo.getSave2Txt()) {
			String txtPath = drcProInfo.getSave2TxtPath() +  "/" + DateUtils.getDate("yyyyMMdd") + ".txt";
			String content = CommTool.getHexString(srcData);
			return saveContent2Txt(content,txtPath);
		}
		return true;
	}
	
	
	public boolean saveContent2Txt(String content,String txtPath) {
		File file = new File(txtPath);
		try {
			
			String parentDir =file.getParent();
			if (!MyPath.check2CreatePath(parentDir))      
			{        
				logger.error(drcProInfo.getParseDataName()+",創建路徑失敗:" + parentDir);
			    CommTool.printInfo(drcProInfo.getParseDataName()+",創建路徑失敗:" + parentDir);
				return false; 
			}
			
			if(!file.exists()) {
				file.createNewFile();
			}
			OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file,true),"GB2312");
			BufferedWriter bw = new BufferedWriter(osw); 
			bw.write(DateUtils.getDate("yyyy-MM-dd HH:mm:ss") + " " + content+"\r\n");
			bw.close();
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error(drcProInfo.getParseDataName()+",將數據保存到TXT失敗:" + e.getMessage());
		    CommTool.printInfo(drcProInfo.getParseDataName()+",將數據保存到TXT失敗:" + e.getMessage());
			return false;
		}
	}
	
	@Override	
    public boolean save() {	
		if(!getDeviceInfo()) return false;
 		if(!getDeviceParamsInfo()) return false;
		if(iniDB()){
			String sql = "insert into data_real(dare_id,devi_id,para_id,dare_value,dare_datetime)"
					+ "values (?,?,?,?,?)";	
			PreparedStatement pstmt;
			
			try {
				pstmt = (PreparedStatement) conn.prepareStatement(sql);
				
				Date da=new Date();	
				pstmt.setString(1, CommTool.uuid());
				pstmt.setString(2, deviceInfo.getDeviId());
				pstmt.setString(3, name2ParamInfoMap.get("負氧離子").getParaId());
				pstmt.setFloat(4, anionData);
				pstmt.setTimestamp(5, new java.sql.Timestamp(da.getTime()));
				
				int res = pstmt.executeUpdate();
				pstmt.close();					
			} catch (SQLException e) {
			    logger.error(drcProInfo.getParseDataName()+",error:"+e.getMessage());
			    CommTool.printInfo(drcProInfo.getParseDataName()+",存儲錯誤");
				return false;
			}
			return true;
		}
		else
			return false;    
	}

	@Override
	public void setDrcProInfo(DrcProInfo drcProInfo) {
		this.drcProInfo=drcProInfo;
	}
	
	@Override
	public DrcProInfo getDrcProInfo() {
		return this.drcProInfo;
	}

	
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章