流程:
建立数据--->Agent读取opc数据--->组建MAS,Agent之间传递数据--->接收数据的远程Agent表格形式显示数据。
遇到的问题
- Exception in thread "main" java.lang.UnsatisfiedLinkError: Directory separator should not appear in library name: ./lib/JCustomOpc
我沿着提示去弄悲剧了,用的是mac,要为自己的土豪和下载的时候没注意看买单了,JEasyOpc只能用windows系统,下载页面有提示。[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好像,我也没弄,挺复杂的,搞工控的人比较懂,所以opc服务器,读opc数据的agent和接收数据并画出图的agent都在本地
[DownLoad]:https://sourceforge.net/projects/jeasyopc/
一. 建立OPC模拟数据(MatrikonOPC Explorer) - 打开桌面应用,连接,建立group,加入item,使用生成器(item页面的item ID右侧图标),命名格式要符合系统默认,比如Bucket Brigade.xxx和Random.xxx等。选Bucket Brigade
- 让数据在一定范围内递增递减变化,选择item,右键write value,选择信号生成器,(a)设定上下限,上限要大于下限,增量可以正负,(b)点击Apply,(c)点击start。没发现范围内随变的设置方法。一次只能一个,窗口关闭就停止变化。或者把频率调成100,然后过会关闭,会一直把缓存输出完才停止。
二. 代码示例
- Jeasyopc库导入
- 首先在src下新建包javafish.clients.opc 将JCustomOpc.properties 拷贝到包中, 然后导入三个jar包jeasyopc.jar commons-logging-1.1.jar和log4j-1.2.13.jar
- 在项目下新建一个lib目录,也可以自定义名字和路径,但是在JCustomOpc.properties 配置中能指定这个目录。将JCustomOpc.dll拷贝到 你定义好的目录下。
- resource文件夹拉倒src目录下(eclipse没找到导入文件夹的方式,可以用直接拖拽的方式)
- jade库导入
- 导入jade.jar,现在的版本只要这个jar包,已经集成到这个包了,网上的好多个都已经没有了
- eclipse下运行代码,右键代码文件,run as - run configuration ,
跳出的页面 Name 添文件名,Main class 填jade.Boot,点击(x)=Arguments 选项卡,program arguments填 -agents agent的名字:包名1.包名2.类名(这步为jade做得,纯java不用)
包名个数根据实际情况,可能没有包名,示例-agents h1:use.RepeatReceive
- java 读写opc数据
- 中文乱码没解决,不过实际过程一般都是数字和英文字符
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对象,三个参数,分别是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());
// 第六步赋值,并同步至服务器
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代码
- 数据要重复传输,本来可以用他的循环行为,但是有很多数据的使用变复杂了,比如内部类,外部数据用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对象,三个参数,分别是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){
// 第六步继续读
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 体积/m³ 流速/m/s");
System.out.println("温度/℃ 湿度/%rh 压强/kPa 体积/m³ 流速/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", "体积/m³",
// "流量/m³" };
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);// 加入數據和字段名構造tablemodel
table = new JTable(defaultModel);// 設置表格模式為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("数据监控");
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();
}
});
}
}