Utgard是一个纯java的opc client api,可以在此基础上编写opc client,运行在window、Linux、mac等平台上;
目前只支持到OPC DA 2.0规范;
官网:http://openscada.org/projects/utgard/
Wiki:https://openscada.atlassian.net/wiki/spaces/OP/overview
编程指导:https://openscada.atlassian.net/wiki/spaces/OP/pages/6094892/HowToStartWithUtgard
github上的测试例子(参照这几个例子,基本上就可以了):
https://github.com/ctron/org.openscada.utgard/tree/1.0/org.openscada.opc.lib.test/src/org/openscada/opc/lib
1、下载添加jar包
下载如下jar包,并添加到eclipse工程的lib目录中,并添加build path;
图中的版本是1.0,当前最新的是1.1.0:
https://github.com/ctron/org.openscada.atlantis/releases
下载最新的版本代码,编译jar包;
【openscada使用slf4j,输出日志,可以自己下载代码,去掉该依赖】
2、测试Main.java
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
public class Main {
public static void main(String[] args) {
String host = "127.0.0.1";// server
String domain = "";// domain
String progId = "ICONICS.SimulatorOPCDA.2";
String user = "OpcUser";// server上的访问用户
String password = "xxxxxx";// 访问用户的密码
OpcClient opcClient = new OpcClient();
// 1.显示server上的opc server应用列表
opcClient.showAllOPCServer(host, user, password, domain);
// 2.连接指定的opc server
boolean ret = opcClient.connectServer(host, progId, user, password, domain);
if (!ret) {
System.out.println("connect opc server fail");
return;
}
// 3.检查opc server上的检测点
List itemIdList = new ArrayList();
itemIdList.add("TEST.FA");
itemIdList.add("TEST.FB");
ret = opcClient.checkItemList(itemIdList);
if (!ret) {
System.out.println("not contain item list");
return;
}
// 4.注册回调
opcClient.subscribe(new Observer() {
@Override
public void update(Observable observable, Object arg) {
Result result = (Result) arg;
System.out.println("update result=" + result);
}
});
// 5.添加监听检测点的数据
// client和server在不同网段,可以访问
opcClient.syncReadObject("TEST.FA", 500);
/**
* TODO 问题
* client和server在不同网段,访问失败,比如:server为10.1.1.132,该网段下面又连接了扩展路由器,192.168.1.x,client为192.168.1.100
*/
opcClient.asyncReadObject("TEST.FB", 500);
// 延迟
delay(5 * 60 * 1000);
}
private static void delay(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3、OpcClient.java,简单封装了opc操作
使用了java自带的观察者模式,回调通知检测点数据;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import org.jinterop.dcom.common.JIException;
import org.openscada.opc.dcom.list.ClassDetails;
import org.openscada.opc.lib.common.AlreadyConnectedException;
import org.openscada.opc.lib.common.ConnectionInformation;
import org.openscada.opc.lib.common.NotConnectedException;
import org.openscada.opc.lib.da.AccessBase;
import org.openscada.opc.lib.da.AccessStateListener;
import org.openscada.opc.lib.da.AddFailedException;
import org.openscada.opc.lib.da.Async20Access;
import org.openscada.opc.lib.da.DataCallback;
import org.openscada.opc.lib.da.DuplicateGroupException;
import org.openscada.opc.lib.da.Item;
import org.openscada.opc.lib.da.ItemState;
import org.openscada.opc.lib.da.Server;
import org.openscada.opc.lib.da.ServerConnectionStateListener;
import org.openscada.opc.lib.da.SyncAccess;
import org.openscada.opc.lib.da.browser.FlatBrowser;
import org.openscada.opc.lib.list.Categories;
import org.openscada.opc.lib.list.Category;
import org.openscada.opc.lib.list.ServerList;
public class OpcClient extends Observable {
private Server mServer = null;
/**
* 连接opc server
*/
public synchronized boolean connectServer(String host, String progId, String user, String password, String domain) {
boolean mState = false;
ServerList serverList = null;
try {
// 获取server上的opc server应用列表
serverList = new ServerList(host, user, password, domain);
// 连接server
final ConnectionInformation connectionInfo = new ConnectionInformation();
connectionInfo.setHost(host);
connectionInfo.setClsid(serverList.getClsIdFromProgId(progId));// TODO 设置ProgId,无法连接server;设置Clsid,连接server成功
connectionInfo.setUser(user);
connectionInfo.setPassword(password);
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
mServer = new Server(connectionInfo, executor);
mServer.connect();
mServer.addStateListener(new ServerConnectionStateListener() {
@Override
public void connectionStateChanged(boolean state) {
System.out.println("connectionStateChanged state=" + state);
}
});
mState = true;
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (JIException e) {
e.printStackTrace();
} catch (AlreadyConnectedException e) {
e.printStackTrace();
} finally {
if (!mState) {
mServer = null;
}
}
return mState;
}
/**
* 断开连接opc server
*/
public synchronized void disconnectServer() {
if (mServer == null) {
return;
}
mServer.disconnect();
mServer = null;
}
/*
* 显示server上的OPC服务器应用列表
*/
public void showAllOPCServer(String host, String user, String password, String domain) {
try {
ServerList serverList = new ServerList(host, user, password, domain);
// 支持DA 1.0,DA 2.0规范
Collection detailsList = serverList.listServersWithDetails(
new Category[] { Categories.OPCDAServer10, Categories.OPCDAServer20 }, new Category[] {});
for (final ClassDetails details : detailsList) {
System.out.println("ClsId=" + details.getClsId() + " ProgId=" + details.getProgId() + " Description="
+ details.getDescription());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 检查opc server中是否包含指定的监测点列表
*/
public boolean checkItemList(List list) {
// 获取opc server上的所有检测点
FlatBrowser flatBrowser = mServer.getFlatBrowser();
if (flatBrowser == null) {
return false;
}
try {
Collection collection = flatBrowser.browse();
return collection.containsAll(list);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 异步读取数据 Async20Access实现了IOPCDataCallback接口,基于事件回调的实现
*/
public void asyncReadObject(final String itemId, int period) {
// 第三个参数用于设置初始化时是否执行访问
AccessBase accessBase;
try {
accessBase = new Async20Access(mServer, period, false);
accessBase.addItem(itemId, new DataCallback() {
@Override
public void changed(Item item, ItemState itemState) {
System.out.println("asyncReadObject item=" + itemState);
try {
Object value = itemState.getValue().getObject();
setData(itemId, value);
} catch (JIException e) {
e.printStackTrace();
}
}
});
// 开始读取
accessBase.bind();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (NotConnectedException e) {
e.printStackTrace();
} catch (JIException e) {
e.printStackTrace();
} catch (DuplicateGroupException e) {
e.printStackTrace();
} catch (AddFailedException e) {
e.printStackTrace();
}
}
/**
* 同步读取数据
*/
public void syncReadObject(final String itemId, int period) {
AccessBase accessBase;
try {
// SyncAccess会开启一个线程,按照period时间间隔,定时去获取监控点数据
accessBase = new SyncAccess(mServer, period);
accessBase.addStateListener(new AccessStateListener() {
@Override
public void stateChanged(boolean state) {
System.out.println("stateChanged state=" + state);
}
@Override
public void errorOccured(Throwable arg) {
System.out.println("errorOccured arg=" + arg);
}
});
accessBase.addItem(itemId, new DataCallback() {
@Override
public void changed(Item item, ItemState itemState) {
System.out.println("syncReadObject item=" + itemState);
if (itemState == null) {
System.out.println("itemState is null");
return;
}
try {
Object value = itemState.getValue().getObject();
setData(itemId, value);
} catch (JIException e) {
e.printStackTrace();
}
}
});
// 开始读取
accessBase.bind();
// 解除绑定,停止读取
// accessBase.unbind();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (NotConnectedException e) {
e.printStackTrace();
} catch (JIException e) {
e.printStackTrace();
} catch (DuplicateGroupException e) {
e.printStackTrace();
} catch (AddFailedException e) {
e.printStackTrace();
}
}
/**
* 注册
*/
public void subscribe(Observer observer) {
this.addObserver(observer);
}
/**
* 数据变化,通知观察者
*/
private void setData(String itemId, Object value) {
setChanged();
notifyObservers(new Result(itemId, value));
}
}
4、检测点数据Result.java
public class Result {
private String itemId;// 监控位置
private Object value;// 监控值
public Result(String itemId, Object value) {
this.itemId = itemId;
this.value = value;
}
public String getItemId() {
return itemId;
}
public Object getValue() {
return value;
}
@Override
public String toString() {
return "[itemId=" + itemId + ", value=" + value + "]";
}
}
配置好opc server模拟器,就可以测试了;