流程:
建立數(shù)據(jù)--->Agent讀取opc數(shù)據(jù)--->組建MAS奴曙,Agent之間傳遞數(shù)據(jù)--->接收數(shù)據(jù)的遠(yuǎn)程Agent表格形式顯示數(shù)據(jù)椎侠。
遇到的問題
- Exception in thread "main" java.lang.UnsatisfiedLinkError: Directory separator should not appear in library name: ./lib/JCustomOpc
我沿著提示去弄悲劇了北专,用的是mac堤结,要為自己的土豪和下載的時候沒注意看買單了绎狭,JEasyOpc只能用windows系統(tǒng)灌侣,下載頁面有提示。[DownLoad]
Java Easy OPC client. The client is based on Java technology. The core library is created in Delphi (only for OS Windows). - opcserver和跑的代碼不在一個機子卖陵,The connection to xxx has failed
要配置DCOM好像遭顶,我也沒弄,挺復(fù)雜的泪蔫,搞工控的人比較懂,所以opc服務(wù)器棒旗,讀opc數(shù)據(jù)的agent和接收數(shù)據(jù)并畫出圖的agent都在本地
[DownLoad]:https://sourceforge.net/projects/jeasyopc/
一. 建立OPC模擬數(shù)據(jù)(MatrikonOPC Explorer) - 打開桌面應(yīng)用,連接撩荣,建立group铣揉,加入item,使用生成器(item頁面的item ID右側(cè)圖標(biāo))餐曹,命名格式要符合系統(tǒng)默認(rèn)逛拱,比如Bucket Brigade.xxx和Random.xxx等。選Bucket Brigade
- 讓數(shù)據(jù)在一定范圍內(nèi)遞增遞減變化凸主,選擇item橘券,右鍵write value,選擇信號生成器卿吐,(a)設(shè)定上下限旁舰,上限要大于下限,增量可以正負(fù)嗡官,(b)點擊Apply箭窜,(c)點擊start。沒發(fā)現(xiàn)范圍內(nèi)隨變的設(shè)置方法衍腥。一次只能一個磺樱,窗口關(guān)閉就停止變化∑畔蹋或者把頻率調(diào)成100竹捉,然后過會關(guān)閉,會一直把緩存輸出完才停止尚骄。
二. 代碼示例
- Jeasyopc庫導(dǎo)入
- 首先在src下新建包javafish.clients.opc 將JCustomOpc.properties 拷貝到包中块差, 然后導(dǎo)入三個jar包jeasyopc.jar commons-logging-1.1.jar和log4j-1.2.13.jar
- 在項目下新建一個lib目錄,也可以自定義名字和路徑倔丈,但是在JCustomOpc.properties 配置中能指定這個目錄憨闰。將JCustomOpc.dll拷貝到 你定義好的目錄下。
- resource文件夾拉倒src目錄下(eclipse沒找到導(dǎo)入文件夾的方式需五,可以用直接拖拽的方式)
- jade庫導(dǎo)入
- 導(dǎo)入jade.jar鹉动,現(xiàn)在的版本只要這個jar包,已經(jīng)集成到這個包了宏邮,網(wǎng)上的好多個都已經(jīng)沒有了
- eclipse下運行代碼泽示,右鍵代碼文件缸血,run as - run configuration ,
跳出的頁面 Name 添文件名边琉,Main class 填jade.Boot属百,點擊(x)=Arguments 選項卡,program arguments填 -agents agent的名字:包名1.包名2.類名(這步為jade做得变姨,純java不用)
包名個數(shù)根據(jù)實際情況族扰,可能沒有包名,示例-agents h1:use.RepeatReceive
- java 讀寫opc數(shù)據(jù)
- 中文亂碼沒解決定欧,不過實際過程一般都是數(shù)字和英文字符
package examples;
import javafish.clients.opc.JOpc;
import javafish.clients.opc.component.OpcGroup;
import javafish.clients.opc.component.OpcItem;
import javafish.clients.opc.exception.ComponentNotFoundException;
import javafish.clients.opc.exception.ConnectivityException;
import javafish.clients.opc.exception.SynchReadException;
import javafish.clients.opc.exception.SynchWriteException;
import javafish.clients.opc.exception.UnableAddGroupException;
import javafish.clients.opc.exception.UnableAddItemException;
import javafish.clients.opc.exception.UnableRemoveGroupException;
import javafish.clients.opc.exception.UnableRemoveItemException;
import javafish.clients.opc.variant.Variant;
import sun.management.HotspotThreadMBean;
public class TestReadWrite {
public static void main(String[] args) throws ConnectivityException, ComponentNotFoundException,
UnableAddGroupException, UnableAddItemException, SynchReadException, UnableRemoveItemException,
UnableRemoveGroupException, SynchWriteException, InterruptedException {
// 第一步渔呵,初始化
// 把配置文件javafish/clients/opc/JCustomOpc.properties、放到classpath
JOpc.coInitialize();
// 第二步砍鸠,建立一個JOpc對象扩氢,三個參數(shù),分別是OpcServer的IP爷辱,Server的name录豺,還有JOpc的name
JOpc jopc = new JOpc("local", "Matrikon.OPC.Simulation.1", "JOPC1");
// 第三步,建立連接
jopc.connect();
// 第四步饭弓,新建一個OPC的group和item双饥,并把item加到group中
OpcGroup group = new OpcGroup("Group0", true, 1000, 0.0f);
OpcItem item = new OpcItem("Bucket Brigade.temp1", true, "");
group.addItem(item);
// 第五步,注冊group弟断,item
jopc.addGroup(group);
jopc.registerGroup(group);
jopc.registerItem(group, item);
// 讀
OpcItem responseItem, responseItem2;
responseItem = jopc.synchReadItem(group, item);
System.out.println("responseItem = " + responseItem.getValue());
// 第六步賦值咏花,并同步至服務(wù)器
item.setValue(new Variant(24));
jopc.synchWriteItem(group, item);
// 等待1秒,寫完太快讀阀趴,讀不到新值
Thread thread = Thread.currentThread();
thread.sleep(1000);
responseItem2 = jopc.synchReadItem(group, item);
System.out.println("responseItem = " + responseItem2.getValue());
// 最后昏翰,該釋放的全釋放掉
jopc.unregisterItem(group, item);
jopc.unregisterGroup(group);
JOpc.coUninitialize();
}
}
4.jade代碼
- 數(shù)據(jù)要重復(fù)傳輸,本來可以用他的循環(huán)行為刘急,但是有很多數(shù)據(jù)的使用變復(fù)雜了棚菊,比如內(nèi)部類,外部數(shù)據(jù)用final才能傳進來叔汁,然后又不能修改等窍株,所以就用while方法了。
//BeReceive.java攻柠,(x)=Arguments 選項卡 -container -host localhost -agents h1:use.RepeatReceive
package use;
import com.sun.corba.se.spi.oa.OADestroyed;
import jade.core.AID;
import jade.core.Agent;
import jade.lang.acl.ACLMessage;
import javafish.clients.opc.JOpc;
import javafish.clients.opc.component.OpcGroup;
import javafish.clients.opc.component.OpcItem;
import javafish.clients.opc.exception.ComponentNotFoundException;
import javafish.clients.opc.exception.ConnectivityException;
import javafish.clients.opc.exception.SynchReadException;
import javafish.clients.opc.exception.UnableAddGroupException;
import javafish.clients.opc.exception.UnableAddItemException;
import javafish.clients.opc.exception.UnableRemoveGroupException;
import javafish.clients.opc.exception.UnableRemoveItemException;
public class BeReceive extends Agent{
public void setup(){
// 第一步,初始化
// 把配置文件javafish/clients/opc/JCustomOpc.properties后裸、放到classpath
JOpc.coInitialize();
// 第二步瑰钮,建立一個JOpc對象,三個參數(shù)微驶,分別是OpcServer的IP浪谴,Server的name开睡,還有JOpc的name
JOpc jopc = new JOpc("local", "Matrikon.OPC.Simulation.1", "JOPC1");
// 第三步,建立連接
try {
jopc.connect();
} catch (ConnectivityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 第四步苟耻,新建一個OPC的group和item篇恒,并把item加到group中
// OpcGroup group = new OpcGroup("TestGroup", true, 1000, 0.0f);
// OpcItem item = new OpcItem("Bucket Brigade.Int1", true, "");
OpcGroup group = new OpcGroup("Group0", true, 1000, 0.0f);
int N = 5;
OpcItem[] items = new OpcItem[N];
OpcItem[] responseItems = new OpcItem[N];
for(int i = 0; i < N; i++){
items[i] = new OpcItem("Bucket Brigade.temp"+(i+1), true, "");
group.addItem(items[i]);
}
//items[0] = new OpcItem("Bucket Brigade.temp1", true, "");
//items[1] = new OpcItem("Bucket Brigade.temp2", true, "");
//group.addItem(items[0]);
//group.addItem(items[1]);
// 第五步,注冊group凶杖,item
jopc.addGroup(group);
try {
jopc.registerGroup(group);
} catch (ComponentNotFoundException | UnableAddGroupException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
for(int i = 0; i < N; i++)
jopc.registerItem(group, items[i]);
} catch (ComponentNotFoundException | UnableAddItemException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 讀
for(int i = 0; i < N; i++)
responseItems[i] = new OpcItem("", true, "");
//System.out.println(responseItem.getValue());
String oldstr ="";
Boolean flag = true;
while(flag){
// 第六步繼續(xù)讀
Thread thread = Thread.currentThread();
try {
thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
for(int i = 0; i < N; i++)
responseItems[i] = jopc.synchReadItem(group, items[i]);
} catch (ComponentNotFoundException | SynchReadException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
StringBuilder sb = new StringBuilder();
for(int i = 0; i < N; i++)
sb.append(responseItems[i].getValue()+" ");
System.out.println(sb.toString());
if(oldstr.equals(sb.toString()))
continue;
oldstr = sb.toString();
System.out.println(oldstr+"11");
ACLMessage message = new ACLMessage(ACLMessage.INFORM);
message.addReceiver(new AID("h2",AID.ISLOCALNAME));//接收端的agent名字要對胁艰,這里用h2
//message.setLanguage("English");
message.setOntology("溫度/℃ 濕度/%rh 壓強/kPa 體積/m3 流速/m/s");
System.out.println("溫度/℃ 濕度/%rh 壓強/kPa 體積/m3 流速/m/s".split(" ").length);
System.out.println(oldstr.split(" ").length);
message.setContent(oldstr);
send(message);
}
// 最后,該釋放的全釋放掉
try {
for(int i = 0; i < N; i++)
jopc.unregisterItem(group, items[i]);
} catch (ComponentNotFoundException | UnableRemoveItemException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
jopc.unregisterGroup(group);
} catch (ComponentNotFoundException | UnableRemoveGroupException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JOpc.coUninitialize();
}
}
//OpAgent.java (x)=Arguments 選項卡 -gui -agents h2:use. OpAgent
package use智蝠;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import jade.core.Agent;
import jade.core.behaviours.SimpleBehaviour;
import jade.lang.acl.ACLMessage;
public class OpAgent extends Agent {
public void setup() {
addBehaviour(new SimpleBehaviour(this) {
@Override
public boolean done() {
// TODO Auto-generated method stub
return false;
}
@Override
public void action() {
// TODO Auto-generated method stub
ACLMessage message = myAgent.receive();
if (message != null) {
String str1 = message.getContent();
String str2 = message.getOntology();
String[] name = str2.split(" ");
String[] value = str1.split(" ");
int len = name.length;
JTable table = null;
DefaultTableModel defaultModel = null;
JFrame frame = new JFrame();
//String[] name2 = str2.split(" "); // { "溫度/℃", "濕度%rh",
// "壓強/kPa", "體積/m3",
// "流量/m3" };
String[][] data = new String[1][len];
for (int j = 0; j < len; j++) {
String k = value[j];
String dString = data[0][j];
//data[0][j] = value[j];
}
defaultModel = new DefaultTableModel(data, name);// 加入數(shù)據(jù)和字段名構(gòu)造tablemodel
table = new JTable(defaultModel);// 設(shè)置表格模式為DefaultTableModel
table.setPreferredScrollableViewportSize(new Dimension(300, 80));
table.setShowVerticalLines(false);
table.setShowVerticalLines(true);
JScrollPane s = new JScrollPane(table);
Container contentPane = frame.getContentPane();
contentPane.add(s, BorderLayout.SOUTH);
frame.setTitle("數(shù)據(jù)監(jiān)控");
frame.pack();
frame.setVisible(true);
while (true) {
//System.out.println("in while");
ACLMessage m = myAgent.receive();
if (m != null) {
str1 = m.getContent();
value = str1.split(" ");
for(int i = 0; i < len; i++)
defaultModel.setValueAt(value[i], 0, i);
} else {
block();
}
defaultModel.fireTableDataChanged();
}
} else
block();
}
});
}
}