首页 > 作文

使用java的milo框架访问OPCUA服务的过程

更新时间:2023-04-04 10:55:50 阅读: 评论:0

最近接了一个项目,需要访问工业的实时数据库,数据库的对外开放接口是opcua协议的,经过多方比对,发现github上milo的评星较高,尝试了一下,还比较方便好用,现在把使用过程中的坑和大家介绍一下,网上比较全的资料不多,下面是整个过程全部的资料:

本次采用keprverex5模拟服务端,使用milo开发的程序作为客户端

一、搭建服务端,keprverex5的安装省略掉,下面是配置过程

设置通道、设备、标签

设置访问的用户名和密码

设置通过opc-ua访问的节点

二、使用milo的框架,开发客户端访问opcua服务

1、在pom文件中追击以下依赖

<!--start milo--><dependency>    <groupid>org.eclip.milo</groupid>    <artifactid>sdk-client</artifactid>    <version>0.2.4</version></dependency><dependency>    <groupid>org.bouncycastle</groupid>    <artifactid>bcpkix-jdk15on</artifactid>    <version>1.57</version></dependency><dependency>    <groupid>org.eclip.milo</groupid>    <artifactid>sdk-rver</artifactid>    <version>0.2.4</version></dependency><!--end milo-->

2、opc ua协议对象接口

package com.jndj.platform.common.milo;import org.eclip.milo.opcua.sdk.client.opcuaclient;import org.eclip.milo.opcua.sdk.client.api.identity.anonymousprovider;import org.eclip.milo.opcua.sdk.client.api.identity.identityprovider;import org.eclip.milo.opcua.stack.core.curity.curitypolicy;import org.eclip.milo.opcua.stack.core.types.structured.endpointdescription;import java.util.concurrent.completablefuture;import java.util.function.predicate;/** * @author yaohj * @date 2020/7/30 * opc ua协议对象接口 */public interface opcuaclientrvice {    /**     * opc ua服务器地址和接口     */    default string getendpointurl() {        return "opc.tcp://127.0.0.1:49320";    }    /**     * 过滤返回的rver endpoint     */    default predicate<endpointdescription> endpointfilter() {        return e -> true;    }    /**     * 连接服务器的安全策略     * none、basic128rsa15、basic256、basic256sha256、aes128_sha256_rsaoaep、aes256_sha256_rsapss     */    default curitypolicy getcuritypolicy() {        return curitypolicy.none;    }    /**     * 提供身份验证     */    default identityprovider getidentityprovider() {        return new anonymousprovider();    }    /**     * 实际操作服务、由实现类重写实现     */    void run(opcuaclient client, completablefuture<opcuaclient> future) throws exception;}

3、opc ua协议对象实体类

package com.jndj.platform.common.milo;import com.google.common.collect.immutablelist;import org.eclip.milo.opcua.sdk.client.opcuaclient;import org.eclip.milo.opcua.stack.core.types.builtin.*;import org.eclip.milo.opcua.stack.core.types.enumerated.timestampstoreturn;import org.springframework.stereotype.rvice;import java.util.list;import java.util.concurrent.completablefuture;@rvice("opcuaclientrvice")public class opcuaclientrviceimpl implements opcuaclientrvice {    /**     * 覆盖接口的方法,建立和opc ua的服务     */    @override    public void run(opcuaclient client, completablefuture<opcuaclient> future) throws exception {        // 同步建立连接        client.connect().get();        // 异步读取数据        readtagdata(client).thenaccept(values -> {            datavalue nodeid_tag1 = values.get(0);            datavalue nodeid_tag2 = values.get(1);            system.out.println("#########tag1=" + nodeid_tag1.getvalue().getvalue());            system.out.println("#########tag2=" + nodeid_tag2.getvalue().getvalue());            future.complete(client);        });    }    /**     * 读取标签点的数据     */    private completablefuture<list<datavalue>> readtagdata(opcuaclient client) {        nodeid nodeid_tag1 = new 苏轼词nodeid(2, "channel1.device1.tag1");        nodeid nodeid_tag2 = new nodeid(2, "channel1.devi观日出ce1.tag2");        list<nodeid> nodeids = immutablelist.of(nodeid_tag1, nodeid_tag2);        return client.readvalues(0.0, timestampstoreturn.both, nodeids);    }}

4、opc ua协议运行对象

package com.jndj.platform.common.milo;import org.eclip.milo.opcua.sdk.client.opcuaclient;import org.eclip.milo.opcua.sdk.client.api.config.opcuaclientconfig;import org.eclip.milo.opcua.sdk.client.api.identity.urnameprovider;import org.eclip.milo.opcua.stack.client.uatcpstackclient;import org.eclip.milo.opcua.stack.core.stack;import org.eclip.milo.opcua.stack.core.types.builtin.localizedtext;import org.eclip.milo.opcua.stack.core.types.structured.endpointdescription;import org.slf4j.logger;import org.slf4j.loggerfactory;import org.springframework.stereotype.rvice;import java.nio.file.files;import java.nio.file.path;import java.nio.file.paths;import java.util.arrays;import java.util.concurrent.completablefuture;import java.util.concurrent.executionexception;import java.util.concurrent.timeunit;import static org.eclip.milo.opcua.stack.core.types.builtin.unsigned.unsigned.uint;@rvice("opcuaclientrunner")public class opcuaclientrunner {    private final logger logger = loggerfactory.getlogger(getclass());    private final completablefuture<opcuaclien英语月份的缩写t> future = new completablefuture<>();    private final opcuaclientrvice opcuaclientrvice;    public opcuaclientrunner(opcuaclientrvice opcuaclientrvice) {        this.opcuaclientrvice = opcuaclientrvice;    }    /**     * opc ua的运行入口程序     */    public void run() {        try {            // 创建opc ua客户端            opcuaclient opcuaclient = createclient();            // future执行完毕后,异步判断状态            future.whencompleteasync((c, ex) -> {                if (ex != null) {                    logger.error("连接opc ua服务错误: {}", ex.getmessage(), ex);                }                // 关闭opc ua客户端                try {                    opcuaclient.disconnect().get();                    stack.releasharedresources();                } catch (interruptedexception | executionexception e) {                    logger.error("opc ua服务关闭错误: {}", e.getmessage(), e);                }            });            try {                // 获取opc ua服务器的数据                opcuaclientrvice.run(opcuaclient, future);                future.get(5, timeunit.conds);            } catch (throwable t) {                logger.error("opc ua客户端运行错误: {}", t.getmessage(), t);                future.completeexceptionally(t);            }        } catch (throwable t) {            logger.error("opc ua客户端创建错误: {}", t.getmessage(), t);            future.completeexceptionally(t);        }    }    /**     * 创建opc ua的服务连接对象     */    private opcuaclient createclient() throws exception {        path curitytempdir = paths.get(system.getproperty("java.io.tmpdir"), "curity");        files.createdirectories(curitytempdir);        if (!files.exists(curitytempdir)) {            throw new exception("不能够创建安全路径: " + curitytempdir);        }        keystoreloader loader = new keystoreloader().load(curitytempdir);        // 获取opc ua的服务器端节点        endpointdescription[] endpoints =                uatcpstackclient.getendpoints(opcuaclientrvice.getendpointurl()).get();        endpointdescription endpoint = arrays.stream(endpoints)                .filter(e -> e.getendpointurl().equals(opcuaclientrvice.getendpointurl()))                .findfirst().orelthrow(() -> new exception("没有节点返回"));        // 设置opc ua的配置信息        opcuaclientconfig config =                opcuaclientconfig.builder()                        .tapplicationname(localizedtext.english("opc ua screen"))                        .tapplicationuri("urn:data-transfer:opc ua screen")                        .tcertificate(loader.getclientcertificate())                        .tkeypair(loader.getclientkeypair())                        .tendpoint(endpoint)                        .tidentityprovider(new urnameprovider("administrator", "123456"))                        .trequesttimeout(uint(5000))                        .build();        // 创建opc ua客户端        return new opcuaclient(config);    }}

5、opc ua访问证书类

package com.jndj.platform.common.milo;import org.eclip.milo.opcua.sdk.rver.util.hostnameutil;import org.eclip.milo.opcua.stack.core.util.lfsignedcertificatebuilder;import org.eclip.milo.opcua.stack.core.util.lfsignedcertificategenerator;import org.slf4j.logger;import org.slf4j.loggerfactory;import java.io.inputstream;import java.io.outputstream;import java.nio.file.files;import java.nio.file.path;import java.curity.*;import java.curity.cert.x509certificate;import java.util.regex.pattern;class keystoreloader {    private final logger logger = loggerfactory.getlogger(getclass());    private static final pattern ip_addr_pattern = pattern.compile(        "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");    // 证书别名    private static final string client_alias = "client-ai";    // 获取私钥的密码    private static final char[] password = "password".tochararray();    // 证书对象    private x509certificate clientcertificate;    // 密钥对对象    private keypair clientkeypair;    keystoreloader load(path badir) throws exception {        // 创建一个使用`pkcs12`加密标准的keystore。keystore在后面将作锁屏壁纸为读取和生成证书的对象。        keystore keystore = keystore.getinstance("pkcs12");        // pkcs12的加密标准的文件后缀是.pfx,其中包含了公钥和私钥。        // 而其他如.der等的格式只包含公钥,私钥在另外的文件中。        path rverkeystore = badir.resolve("example-client.pfx");        logger.info("loading keystore at {}", rverkeystore);        // 如果文件不存在则创建.pfx证书文件。        if (!files.exists(rverkeystore)) {            keystore.load(null, password);            // 用2048位的ras算法。`lfsignedcertificategenerator`为milo库的对象。            keypair keypair = lfsignedcertificategenerator.generatersakeypair(2048);            // `lfsignedcertificatebuilder`也是milo库的对象,用来生成证书。            // 中间所设置的证书属性可以自行修改。            lfsignedcertificatebuilder builder = new lfsignedcertificatebuilder(keypair)                .tcommonname("eclip milo example client")                .torganization("digitalpetri")                .torganizationalunit("dev")                .tlocalityname("folsom")                .tstatename("ca")                .tcountrycode("us")                .tapplicationuri("urn:eclip:milo:examples:client")                .adddnsname("localhost")                .addipaddress("127.0.0.1");            // get as many hostnames and ip address as we can listed in the certificate.            for (string hostname : hostnameutil.gethostnames("0.0.0.0")) {                if (ip_addr_pattern.matcher(hostname).matches()) {                    builder.addipaddress(hostname);                } el {                    builder.adddnsname(hostname);                }            }            // 创建证书            x509certificate certificate = builder.build();            // 设置对应私钥的别名,密码,证书链            keystore.tkeyentry(client_alias, keypair.getprivate(), password, new x509certificate[]{certificate});            try (outputstream out = files.newoutputstream(rverkeystore)) {                // 保存证书到输出流                keystore.store(out, password);            }        } el {            try (inputstream in = files.newinputstream(rverkeystore)) {                // 如果文件存在则读取                keystore.load(in, password);            }        }        // 用密码获取对应别名的私钥。        key rverprivatekey = keystore.getkey(client_alias, password);        if (rverprivatekey instanceof privatekey) {            // 获取对应别名的证书对象。            clientcertificate = (x509certificate) keystore.getcertificate(client_alias);            // 获取公钥            publickey rverpublickey = clientcertificate.getpublickey();            // 创建keypair对象。            clientkeypair = new keypair(rverpublickey, (privatekey) rverprivatekey);        }        return this;    }    // 返回证书    x509certificate getclientcertificate() {        return clientcertificate;    }    // 返回密钥对    keypair getclientkeypair() {        return clientkeypair;    }}

6、业务rvice类

package com.jndj.platform.pha2.rvice.impl;import com.jndj.platform.common.milo.opcuaclientrunner;import com.jndj.platform.common.milo.opcuaclientrvice;import com.jndj.platform.pha2.rvice.pha2rvice;import org.springframework.beans.factory.annotation.autowired;import org.springframework.stereotype.rvice;/** * @author yaohj * @date 2020/7/22 * 获取二期发电数据(三、四号机组) */@rvice("pha2rvice")public class pha2rviceimpl implements pha2rvice {    @autowired    private opcuaclientrvice opcuaclientrvice;    /**     * 获取二期发电数据(三、四号机组),保存到数据库中     */    @override    public void 保护动物的广告archpha2electricdata() {        new opcuaclientrunner(opcuaclientrvice).run();    }}

7、业务controller类、定时调度

package com.jndj.platform.pha2.controller;import com.jndj.platform.pha2.rvice.pha2rvice;import org.slf4j.logger;import org.slf4j.loggerfactory;import org.springframework.beans.factory.annotation.autowired;import org.springframework.scheduling.annotation.scheduled;import org.springframework.stereotype.controller;import java.text.simpledateformat;import java.util.date;/** * @author yaohj * @date 2020/7/22 * 获取二期发电数据(三、四号机组) */@controllerpublic class pha2controller {    private static final logger logger = loggerfactory.getlogger(pha2controller.class);    private static final simpledateformat dateformat = new simpledateformat("yyyy:mm:dd hh:mm:ss");    @autowired    private pha2rvice pha2rvice;    /**     * 获取二期发电数据(三、四号机组),保存到数据库中(x分钟调度一次)     */    @scheduled(initialdelay = 30000, fixedrate = 30000)    public void archgasdata() {        logger.info("####获取二期发电数据(三、四号机组) - 定时任务执行时间:"+ dateformat.format(new date()));        pha2rvice.archpha2electricdata();    }}

8、运行结果、定时获取到opcua服务中的数据

ok,以上是所有的源代码,大家的问题基本能够解决。

到此这篇关于使用java的milo框架访问opcua服务的方法的文章就介绍到这了,更多相关java访问opcua服务内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-04 10:55:48,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/c6029fa967af7f9880c8b7b12f961026.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:使用java的milo框架访问OPCUA服务的过程.doc

本文 PDF 下载地址:使用java的milo框架访问OPCUA服务的过程.pdf

标签:证书   对象   数据   客户端
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图