JAVA通过COM方式(jeasyopc)接入OPC DA

本文详细介绍使用jeasyopc库在Windows环境下通过COM方式对接OPC DA的过程。包括源码修改、打包、配置及SpringBoot项目的集成。提供了启动初始化、查询及控制OPC数据的API示例。

至于使用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如何编译

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值