至于使用jeasyopc方式对接OPC DA,可以详见上两篇文章。jeasyopc只能运行在windows上,本地使用COM方式连接。但其中也有不少坑,网上完整的实现很少,本人先填为敬。
实现已开源,需要的自行获取:jeasyopc.win.driver
部署到OPC服务器上,使用本地连接,并提供API接口进行查询及控制。
jeasyopc源码下载:jeasyopc
32位java sdk:可从官网下载或者:(jdk-8u351-windows-i586.exe)
JCustomOpc.dll:在下载jeasyopc/lib中。
默认使用ClassLoader方式进行读取配置文件,IDE使用时没问题,但编译为jar包时会无法读取到配置文件,修改源代码PropertyLoader.java:
ClassLoader cl = ClassLoader.getSystemClassLoader();
//修改为
ClassLoader cl = PropertyLoader.class.getClassLoader();
这里未写打包脚本:
javac -cp "lib/*" -d target src\javafish\clients\opc\*.java src\javafish\clients\opc\asynch\*.java src\javafish\clients\opc\browser\*.java src\javafish\clients\opc\component\*.java src\javafish\clients\opc\exception\*.java src\javafish\clients\opc\lang\*.java src\javafish\clients\opc\property\*.java src\javafish\clients\opc\variant\*.java
jar -cvfm jeasy2.3.2.jar META-INF\MANIFEST.MF .
或者使用sh脚本:
#!/bin/bash
set -e
if [ ! -d "target" ];then
mkdir target
cp -a META-INF target
else
echo "start"
fi
find -name "*.java" > list.txt
javac -cp "lib/*" -sourcepath src @list.txt -d target
cd target
jar -cvfm jeasy2.3.2.jar META-INF/MANIFEST.MF .
echo "build succcess ..."
打包并安装到本地/私有仓库,后续需要依赖使用。
spring boot项目,配置文件都在resources目录下。jeapsyopc的配置文件放于:
resources\javafish\clients\opc\JCustomOpc.properties,配置包含library.path = ./lib/JCustomOpc,配置JCustomOpc.dll的存储位置,注意:我这里的./lib配置说明,IDE放在项目根目录/lib目录下,打为jar包后,放在与jar同级文件夹lib下。
注意二:
在调试过程中发现一直报错 jeasyopc Translate doesn't exist. System terminated. 语言资源文件需要放到resources中:打包解压到resources目录中即可。
链接: https://pan.baidu.com/s/1CFy2_1M6XDdV3ZYN-u7o5g?pwd=8t3s
提取码: 8t3s
启动初始化group,opcDaService.java:
@PostConstruct
private void initOpc() {
boolean b = opcInit();
if (!b) {
log.error("JOPC 连接失败,开始重连。");
reconnect();
} else {
log.info("JOPC 连接成功");
}
}
/**
* 初始化opc服务
*/
private boolean opcInit() {
log.info("JOPC 开始初始化");
try {
JOpc.coInitialize();
// List All Servers
String[] opcServers = JOpcBrowser.getOpcServers(opcConfig.getHost());
for (String server : opcServers) {
log.info("-----[server]-----:" + server);
}
log.info("建立JOPC服务对象");
jopc = new JOpc(opcConfig.getHost(), opcConfig.getProgId(), "JOPC1");
jopc.connect();
// jOpcBrowser = new JOpcBrowser(opcConfig.getHost(), opcConfig.getProgId(), "JOPCBrowser1");
// jOpcBrowser.connect();
// 初始化组 -- 我这里使用json提前配置所有的分组情况
String jsonContent = Utils.readFile(opcConfig.getGroupJson());
if (jsonContent.isEmpty()) {
throw new RuntimeException("JOPC 请选择正确的json文件");
}
JSONArray groups = JSON.parseArray(jsonContent);
for (Object group : groups) {
JSONObject groupJsonObj = (JSONObject) group;
String groupId = groupJsonObj.getString("group");
log.info("JOPC 新增组:{}", groupId);
OpcGroup opcGroup = new OpcGroup(groupId, true, 100, 0.0f);
JSONArray items= groupJsonObj.getJSONArray("items");
for (Object item: items) {
String itemId= (String) item;
OpcItem opcItem = new OpcItem(itemId, true, "");
opcGroup .addItem(opcItem);
log.info("JOPC 新增item:{}", opcItem);
}
jopc.addGroup(opcGroup );
groupSourceMap.put(groupId, opcGroup);
}
log.info("JOPC 开始注册分组");
jopc.registerGroups();
log.info("JOPC 注册分组成功");
} catch (Exception e) {
log.error("JOPC 连接异常", e);
return false;
}
return true;
}
/**
* 断开连接
*/
@PreDestroy
private void coUninitialize() {
log.info("JOPC 断开连接");
JOpc.coUninitialize();
}
public OpcGroup getGroupById(String id) {
return groupSourceMap.get(id);
}
controller:
@GetMapping("ping")
public Result ping() {
JOpc jopc = opcDaService.getOpcInstance();
if (Objects.isNull(jopc)) {
return ResultGenerator.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "OPC服务异常");
}
return ResultGenerator.success();
}
@GetMapping("query")
public Result query(@RequestParam("group") String groupId) {
JOpc jopc = opcDaService.getOpcInstance();
if (Objects.isNull(jopc)) {
return ResultGenerator.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "OPC服务异常");
}
// 获取分组
OpcGroup groupById = opcDaService.getGroupById(groupId);
if (Objects.isNull(groupById )) {
return ResultGenerator.fail(ResultCode.FAIL.getCode(), "未查询到该分组");
}
OpcGroup responseGroup = null;
try {
responseGroup = jopc.synchReadGroup(groupById);
} catch (SynchReadException e) {
log.error("查询组状态失败,查询ID:{}", groupId, e);
return ResultGenerator.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "查询异常【" + e.getMessage() + "】");
}
ArrayList<OpcItem> items = responseGroup.getItems();
ArrayList<Object> objects = new ArrayList<>();
for (OpcItem item : items) {
JSONObject jsonObject = new JSONObject();
Variant value = item.getValue();
jsonObject.put("itemId", item.getItemName());
int returnValue;
if (!item.isQuality()) {
returnValue = -1;
} else {
if (Variant.VT_BOOL == item.getDataType()) {
returnValue = value.getBoolean() ? 1 : 0;
} else {
returnValue = -1;
}
}
jsonObject.put("type", Variant.getVariantName(item.getDataType()));
jsonObject.put("status", returnValue);
objects.add(jsonObject);
}
return ResultGenerator.success(objects);
}
@PutMapping("write")
public Result write(@RequestBody JSONObject params) {
String id = params.getString("group");
if (Objects.isNull(id)) {
return ResultGenerator.fail(ResultCode.FAIL.getCode(), "请输入要修改的组地址");
}
// 获取分组
OpcGroup group = opcDaService.getGroupById(id);
if (Objects.isNull(group)) {
return ResultGenerator.fail(ResultCode.FAIL.getCode(), "该分组不存在");
}
Integer status = params.getInteger("status");
if (Objects.isNull(status)) {
return ResultGenerator.fail(ResultCode.FAIL.getCode(), "请输入要修改的状态0/1");
}
JOpc jopc = opcDaService.getOpcInstance();
if (Objects.isNull(jopc)) {
return ResultGenerator.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "OPC服务异常");
}
// 获取当前分组的唯一item
OpcItem opcItem = group.getItems().get(0);
Variant varin = new Variant(!status.equals(0));
opcItem.setValue(varin);
try {
jopc.synchWriteItem(group, opcItem);
} catch (SynchWriteException e) {
log.error("写入组状态失败,用户参数:{}", params, e);
return ResultGenerator.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "控制异常【" + e.getMessage() + "】");
}
return ResultGenerator.success();
}
@echo off
java -DSERVR_PORT=18081 -Dspring.profiles.active=debug -jar opcda-1.0.0.jar
pause
luoyan35714/OPC_Client
I don’t know how to install JEasyOPC in Java
Java 打 jar 包的几种方式详解
Jade应用opc服务器的数据展示
java读取opc服务器
抛开IDE,了解一下javac如何编译