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


    超短连接转换j1z.cc(永久有效)

    至于使用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();
    
    • 1
    • 2
    • 3

    原始打包命令

    这里未写打包脚本:

    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 .
    
    • 1
    • 2
    • 3

    或者使用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 ..."
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    打包并安装到本地/私有仓库,后续需要依赖使用。

    目录结构说明

    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);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    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();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    启动

    @echo off
    java -DSERVR_PORT=18081 -Dspring.profiles.active=debug -jar opcda-1.0.0.jar
    pause
    
    • 1
    • 2
    • 3

    参考

    luoyan35714/OPC_Client
    I don’t know how to install JEasyOPC in Java
    Java 打 jar 包的几种方式详解
    Jade应用opc服务器的数据展示
    java读取opc服务器
    抛开IDE,了解一下javac如何编译

  • 相关阅读:
    数据恢复软件 –最好的Android数据恢复软件分享
    数据结构与算法-时间复杂度与空间复杂度
    解决连接数据库提示:Public Key Retrieval is not allowed
    GCP认证考试之BigQuery专题
    Python小程序 - 文件处理2 (使用AI工具 完整提问)
    【智慧零售】门店管理设备解决方案,为企业数字化运营升级赋能
    Ant-Design-Pro使用QianKun微前端最佳实践
    JS执行上下文与闭包的理解
    【MySQL】基本查询(三)聚合函数+group by
    Python实现极限学习机回归模型(ELMRegressor算法)项目实战
  • 原文地址:https://blog.csdn.net/Tuine/article/details/127984833