5 實(shí)例
以一個(gè)交流調(diào)速網(wǎng)絡(luò)監(jiān)控系統(tǒng)為例說明網(wǎng)絡(luò)監(jiān)控軟件的開發(fā)。系統(tǒng)組成見圖2。
圖2 交流調(diào)速網(wǎng)絡(luò)監(jiān)控系統(tǒng)
系統(tǒng)采用Java結(jié)合C++進(jìn)行系統(tǒng)設(shè)計(jì)。需要用到Java Socket、JNI、JDBC、Java多線程以及C++ DLL等應(yīng)用。
(1) 現(xiàn)場(chǎng)端實(shí)現(xiàn)現(xiàn)場(chǎng)數(shù)據(jù)的收集
① 由JNI調(diào)用C++ DLL實(shí)現(xiàn)轉(zhuǎn)速反饋數(shù)據(jù)的采集
系統(tǒng)由JNI調(diào)用操作數(shù)據(jù)采集卡的DLL完成實(shí)時(shí)數(shù)據(jù)的采集。如類ACTimingNC.java
public class ACTimingNC
{ ......
public native short inport(short port); //聲明本地方法inport(),
public native void outport(short port,int value); //聲明本地方法outport()
public native float sample(short base,int num);//聲明本地方法sample()
static{ System.loadLibrary("PCL8112.dll");} //調(diào)入本地庫(kù)
//聲明三種本地方法:inport()用于返回?cái)?shù)據(jù)采集卡端口號(hào),outport()用于向指定的端口輸出數(shù)值,sample()用于啟動(dòng)采樣,返回采集到的數(shù)據(jù)。
public static void main(String args[])
{ ACTimingNC ACtiming=new ACTimingNC("交流調(diào)速網(wǎng)絡(luò)監(jiān)控現(xiàn)場(chǎng)端");
...... } }
然后在命令提示符下鍵入javac ACTimingNC.java進(jìn)行編譯生成ACTimingNC.class,再運(yùn)行javah ACTimingNC,得到C++文件ACTimingNC.h,然后編制相應(yīng)的ACTimingNC.cpp文件實(shí)現(xiàn)對(duì)應(yīng)的本地方法即可,最后編譯形成動(dòng)態(tài)鏈接庫(kù)DLL文件,放到應(yīng)用程序路徑下。運(yùn)行時(shí)就實(shí)現(xiàn)了Java調(diào)用DLL對(duì)硬件的操作。
② Java串口包實(shí)現(xiàn)對(duì)變頻器的參數(shù)查詢和控制
利用Sun公司提供的串口包,再結(jié)合臺(tái)達(dá)變頻器的控制協(xié)議,就可以實(shí)現(xiàn)雙方的數(shù)據(jù)交流了。例如控制命令串的發(fā)送代碼如下:
import java.io.*;import java.util.*;import javax.comm.*;
class SerialportIO
{ public static void main(String args[])
{ …… //得到對(duì)串口COM1的控制權(quán)
try{ serialPort.setSerialPortParams(4800,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_ODD);
//實(shí)施臺(tái)達(dá)變頻器串口協(xié)議:波特率、數(shù)據(jù)位、停止位和奇偶校驗(yàn)位分別為4800、8、1、O(奇校驗(yàn))。
}catch(UnsupportedCommOperationException e3){}
try{ String s="......"; //s為控制命令串,具體參照說明書
os.writeUTF(s); }catch(IOException e3){} }}}}}
(2) 由Java Socket實(shí)現(xiàn)數(shù)據(jù)在現(xiàn)場(chǎng)端和服務(wù)器端的傳輸
例如從現(xiàn)場(chǎng)端向服務(wù)器端傳送數(shù)據(jù):由現(xiàn)場(chǎng)端提交監(jiān)測(cè)數(shù)據(jù),數(shù)據(jù)服務(wù)器端接收數(shù)據(jù)。現(xiàn)場(chǎng)端部分代碼如下:
public class SceneServer //數(shù)據(jù)服務(wù)器端
{ public static void main(String args[])
{ try{ Socket socket=new Socket("202.199.133.46",PORT); //與服務(wù)器建立連接
PrintStream os=new PrintStream(wss.getOut- putStream()); //輸出流
DataInputStream is=new DataInputStream(wss.get- InputStream());//輸入流
StringBuffer buf=new StringBuffer(100); //定義數(shù)據(jù)緩沖區(qū)
... ...//進(jìn)行數(shù)據(jù)發(fā)送
}catch(IOException e) {} } }
在數(shù)據(jù)服務(wù)器端,考慮到以后系統(tǒng)的擴(kuò)展,可能有多臺(tái)現(xiàn)場(chǎng)端智能設(shè)備提出發(fā)送數(shù)據(jù)請(qǐng)求,所以程序必須實(shí)現(xiàn)多線程。部分代碼如下:
public class DSServer //數(shù)據(jù)服務(wù)器端
{ public static final PORT=5000; ServerSocket ss=null; Socket s=null;
public static void main(String args[])
{ try{ ss=new ServerSocket(PORT);
while(true) {s=ss.accept(); new ServerThread(s).start(); }
}catch(IOException e1) {} ... ... } }
class ServerThread extends Thread
{ Socket socket=null;
ServerThread(Socket socket)
{ super("ServerThread"); this.socket=socket; }
public void run()
{ ……//接通輸入輸出流,實(shí)現(xiàn)數(shù)據(jù)傳輸以及操作到庫(kù)。 } }
這段程序由兩個(gè)類組成,主類SceneServer負(fù)責(zé)建立處理連接請(qǐng)求,線程類ServerThread用于創(chuàng)建一個(gè)新的線程,負(fù)責(zé)處理現(xiàn)場(chǎng)端的輸入輸出請(qǐng)求。反方向的控制信息傳輸只要加入相應(yīng)代碼即可。
(3) 服務(wù)器端采用JSP結(jié)合Java Bean實(shí)現(xiàn)監(jiān)控
① 由JDBC訪問SQL Server2000數(shù)據(jù)庫(kù)
對(duì)于本系統(tǒng),在SQL Server中需建立用戶表Users、設(shè)備表Devices、實(shí)時(shí)數(shù)據(jù)表RTData、歷史數(shù)據(jù)表HistoryData。用戶表用于進(jìn)行身份驗(yàn)證,不同的用戶有不同的管理權(quán)限;而設(shè)備表包括現(xiàn)場(chǎng)設(shè)備的清單及其狀態(tài);實(shí)時(shí)數(shù)據(jù)表保存實(shí)時(shí)數(shù)據(jù),如可以保存一天內(nèi)的實(shí)時(shí)數(shù)據(jù),在本系統(tǒng)中主要指轉(zhuǎn)速反饋、工作電流、工作頻率,然后每天將當(dāng)天數(shù)據(jù)挪進(jìn)歷史數(shù)據(jù)表;歷史數(shù)據(jù)表用于保存一段時(shí)期中的運(yùn)行數(shù)據(jù)。于是Web服務(wù)器可以根據(jù)客戶端的不同請(qǐng)求作出響應(yīng),由JDBC操作數(shù)據(jù)庫(kù)。這里數(shù)據(jù)庫(kù)實(shí)際上成為了現(xiàn)場(chǎng)數(shù)據(jù)上傳和控制信息下達(dá)的通信中樞。部分代碼如下:
import java.sql.*;
class DataIO
{ public static void main(String args[])
{ try{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //驅(qū)動(dòng)器
String url="jdbc:odbc:ACTiming"; //數(shù)據(jù)源
con=DriverManager.getConnection(url,"",""); //連接數(shù)據(jù)庫(kù)
state=con.createStatement();
String query="select freq,curr,rev from HistoryData where DeviceID=1 and date>20030410 and date<20030412"; //例如查看歷史數(shù)據(jù)表中1號(hào)設(shè)備在2003-4-10到2003-4-12號(hào)之間頻率、電流、轉(zhuǎn)速的運(yùn)行數(shù)據(jù)。
ResultSet result=statement.executeQuery(query);
... ... //然后可以從結(jié)果集中取數(shù)據(jù)分析或送顯
}catch(Exceptione) ystem.out.println(e.toString());} }
② 系統(tǒng)的登陸
對(duì)不同的用戶登陸給出不同的操作界面。系統(tǒng)管理管理員可以完全操作整個(gè)系統(tǒng),包括用戶管理、系統(tǒng)管理;對(duì)不同的現(xiàn)場(chǎng)系統(tǒng)的負(fù)責(zé)人只能監(jiān)控自己的系統(tǒng);而對(duì)網(wǎng)上演示,允許游客登陸只能觀看給定的系統(tǒng),不能控制。登陸界面通過JSP連接用戶表進(jìn)行身份驗(yàn)證,通過驗(yàn)證后給出相應(yīng)界面。
③ 其他,如顯示曲線類、數(shù)據(jù)分析類、報(bào)表打印類等
這些類均可以制作成Java Bean,嵌入JSP中實(shí)現(xiàn)。其功能分別實(shí)現(xiàn)接收到數(shù)據(jù)后的趨勢(shì)曲線繪制和顯示,可以采用雙緩沖技術(shù)來進(jìn)行。數(shù)據(jù)分析可以實(shí)現(xiàn)一定的智能算法,以便進(jìn)行在線系統(tǒng)分析、故障預(yù)測(cè)等。報(bào)表打印類實(shí)現(xiàn)打印報(bào)表,包括故障報(bào)警記錄、歷史記錄、當(dāng)天記錄等等。
6 結(jié)語(yǔ)
基于Java進(jìn)行網(wǎng)絡(luò)監(jiān)控軟件的開發(fā)可以充分利用Java的網(wǎng)絡(luò)特性,并可以集成C++代碼,實(shí)現(xiàn)本地系統(tǒng)控制與遠(yuǎn)程網(wǎng)絡(luò)監(jiān)控的統(tǒng)一,極大地提高了軟件開發(fā)效率。對(duì)交流調(diào)速網(wǎng)絡(luò)監(jiān)控軟件的設(shè)計(jì)過程以及實(shí)驗(yàn)室校園網(wǎng)環(huán)境下的調(diào)試運(yùn)行顯示系統(tǒng)性能良好。進(jìn)一步完善軟件系統(tǒng)設(shè)計(jì)以及進(jìn)行在線算法調(diào)整和控制是今后研究中很有意義的課題。