文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

【应用】OPC 通讯协议

2023-10-24 14:31

关注

OPC 通讯协议

OPC 通讯协议基础

OPC 简介

OPC 全称 OLE For Process Control,即用于控制过程的 OLE,是一个工业标准,管理该标准的国际组织是 OPC 基金会。

OPC 出现的目的是为不同的供应商设备与应用程序之间的接口标准化从而使其间的数据交换更加简单,因此,使我们可以开发不依靠于特定开发语言和开发环境的、可以自由组合的过程控制软件。

利用驱动器的系统连接
在这里插入图片描述
利用 OPC 控制的系统组成
在这里插入图片描述

OPC 的分层结构

OPC 对象中最上层的对象是 OPC 服务器,一个 OPC 服务器中可以设置一个以上的 OPC 组。OPC 服务器常对应于某种特定的控制设备,如 DCS 以及 PLC 等。

OPC 组是可以进行数据访问的多个 OPC 标签的集合,OPC 应用程序可以将需要的数据分组进行批量读取,也可以以组为单位启动或者停止数据访问。此外,OPC 组还提供组内 OPC 标签数据变化时向 OPC 应用程序通知的事件。

在这里插入图片描述

OPC 与 OPC UA

OPC DA 与 OPC UA 都是 OPC 协议的标准:

举例说明两者之间的区别:

对传统的三种不同类型OPC服务器的访问:数据访问 DA、报警和事件 AE、历史数据访问 HDA,要获得一个温度传感器的当前值、一个高温度事件和温度的历史平均值,要依次使用不同的命令执行;

而使用 OPC UA,仅用一个组件就非常容易地完成了。配置和工程的时间也因此可以大大缩短。

OPC 逻辑对象模型

包括3类对象:OPC Server 对象、OPC Group 对象、OPC Item 对象,每类对象都包括一系列接口。

OPC Server 对象

主要功能:

OPC Group 对象

主要功能:

属性:

注意:

OPC Item 对象

主要功能:

属性:

注意:

OPC 通信方式

Java 实现 OPC 的方式

OPC Client 开发大致流程

  1. COM 组件初始化;
  2. 创建服务器 Server 对象;
  3. 创建组 Group 对象;
  4. 创建项 Item 对象;
  5. 添加 Item 到 Group 中;
  6. 添加 Group 到 Server 对象中;
  7. 连接服务器,完成相应操作;
  8. COM 组件关闭

OPC DA

Java 关于 OPC DA 的开源库只有 Utgard 和 Jeasyopc,两者区别如下:

UtgardJeasyopc
Linux支持不支持
Windows支持不支持
用户名和密码需要不需要
组查询支持不支持
压力测试(单线程同步)略快 7W 点约 4224ms略慢 7W 点约 22540ms
DCOM通过 DCOM 实现,需进行配置不需要配置
开源库现状作者删库跑路只支持 32 位系统

OPC UA

推荐使用 Eclipse 的 milo 开源库

Java 实现 OPC-client

本测试使用的 OPC-Server 软件为 KEPServerEX6,具体下载与使用参考博客OPCServer:使用KEPServer

OPC-DA

因为开源库 Jeasyopc 不支持 windows 和 linux 系统,且只支持 32 位系统,因此此处使用 Utgard 库实现。本测试采用虚拟机实现,使用的系统为 Windows 10 专业版,版本号 1903。

Utgard 开源库通过 DCOM 技术实现,因此首先需要配置 DCOM,参考博客OPC和DCOM配置

引入相应的依赖

        <dependency>            <groupId>org.kohsuke.jinteropgroupId>            <artifactId>j-interopartifactId>            <version>2.0.5version>        dependency>        <dependency>            <groupId>org.openscada.utgardgroupId>            <artifactId>org.openscada.opc.libartifactId>            <version>1.5.0version>        dependency>

从 OPC-Server 读取数据

public class OPCRead {    public static void main(String[] args) {        // 配置连接信息        final ConnectionInformation ci = new ConnectionInformation();        ci.setHost("localhost");         // 本机IP        ci.setDomain("");                // 域,为空就行        ci.setUser("OPCServer");         // 用户名        ci.setPassword("OPCServer");     // 密码        // 配置 KEPServer        ci.setClsid("7BC0CC8E-482C-47CA-ABDC-0FE7F9C6E729"); // KEPServer 的注册表ID,可以在“组件服务”里看到        final String itemId = "通道 1.设备 1.标记 2";    // KEPServer 上配置的项的名字        // 启动服务        final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());        try {            // 连接服务器            server.connect();            // 创建 Group,用于对 Item 的访问            final Group group = server.addGroup("test");            // 将要访问的 Item 加入创建的 Group            final Item item = group.addItem(itemId);            // 读取 Item 状态            ItemState itemState = item.read(true);            // 获取 Item 的数据类型,该类型使用常量定义,见 JIVariant 类            int type = 0;            try {                type = itemState.getValue().getType(); // 类型实际是数字,用常量定义的            } catch (JIException e) {                e.printStackTrace();            }            // 打印 Item 相应状态            System.out.println(">>>监控项的数据类型是:" + type);            System.out.println(">>>监控项的时间戳是:" + itemState.getTimestamp().getTime());            System.out.println(">>>监控项的详细信息是:" + itemState);            // 若读到是 short 类型(对应数字 2)            if (type == JIVariant.VT_I2) {                short value = 0;                try {                    value = itemState.getValue().getObjectAsShort();                } catch (JIException e) {                    e.printStackTrace();                }                System.out.println(">>>short类型值: " + value);            }            // 删除 Group            server.removeGroup(group, true);        } catch (Exception e) {            throw new RuntimeException(e);        }    }}

从 OPC-Server 写入数据

public class OPCWrite {    public static void main(String[] args) {        // 配置连接信息        final ConnectionInformation ci = new ConnectionInformation();        ci.setHost("localhost");         // 本机IP        ci.setDomain("");                // 域,为空就行        ci.setUser("OPCServer");         // 用户名        ci.setPassword("OPCServer");     // 密码        // 配置 KEPServer        ci.setClsid("7BC0CC8E-482C-47CA-ABDC-0FE7F9C6E729"); // KEPServer 的注册表ID,可以在“组件服务”里看到        final String itemId = "通道 1.设备 1.标记 2";    // KEPServer 上配置的项的名字        // 启动服务        final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());        try {            // 连接服务器            server.connect();            // 创建 Group,用于对 Item 的访问            final Group group = server.addGroup("test");            // 将要访问的 Item 加入创建的 Group            final Item item = group.addItem(itemId);            // 写入前:打印 Item 状态及对应数据            printRead(item);            // 写入数据            item.write(new JIVariant("100"));            // 写入后:打印 Item 状态及对应数据            printRead(item);            // 删除 Group            server.removeGroup(group, true);        } catch (Exception e) {            throw new RuntimeException(e);        }    }        public static void printRead(Item item) throws JIException {        // 读取 Item 状态        ItemState itemState = item.read(true);        int type = 0;        try {            type = itemState.getValue().getType(); // 类型实际是数字,用常量定义的        } catch (JIException e) {            e.printStackTrace();        }        // 打印 Item 相应状态        System.out.println(">>>监控项的数据类型是:" + type);        System.out.println(">>>监控项的时间戳是:" + itemState.getTimestamp().getTime());        System.out.println(">>>监控项的详细信息是:" + itemState);        // 若读到是 short 类型(对应数字 2)        if (type == JIVariant.VT_I2) {            short value = 0;            try {                value = itemState.getValue().getObjectAsShort();            } catch (JIException e) {                e.printStackTrace();            }            System.out.println(">>>short类型值: " + value);        }    }}

OPC-UA

OPC-UA 是目前比较流行的协议,采用开源库 milo 实现,引入相应依赖:

        <dependency>            <groupId>org.eclipse.milogroupId>            <artifactId>sdk-clientartifactId>            <version>0.6.3version>        dependency>        <dependency>            <groupId>org.eclipse.milogroupId>            <artifactId>sdk-serverartifactId>            <version>0.6.3version>        dependency>

使用 opc-ua 实现数据读写:

public class OpcUaDemo {    public static void main(String[] args) throws Exception {        // 创建OPC UA客户端        OpcUaClient opcUaClient = createClient();        // 开启连接        opcUaClient.connect().get();        // 遍历节点        browseNode(opcUaClient, null);        // 读        readNode(opcUaClient);        // 写        writeNodeValue(opcUaClient);        readNode(opcUaClient);        // 关闭连接        opcUaClient.disconnect().get();    }        private static OpcUaClient createClient() throws Exception {        String endPointUrl = "opc.tcp://127.0.0.1:49320";        Path securityTmpdir = Paths.get(System.getProperty("java.io.tmpdir"), "security");        Files.createDirectories(securityTmpdir);        if (!Files.exists(securityTmpdir)) {            throw new Exception("unable to create security dir: " + securityTmpdir);        }        return OpcUaClient.create(endPointUrl,                endpoints ->                        endpoints.stream()    .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))    .findFirst(),                configBuilder ->                        configBuilder    .setApplicationName(LocalizedText.english("KEPServerEX/UA Client Driver"))    .setApplicationUri("urn:Thinkbook-ZQF:Kepware.KEPServerEX.V6:UA%20Client%20Driver")    //访问方式    .setIdentityProvider(new AnonymousProvider())    .setRequestTimeout(UInteger.valueOf(5000))    .build()        );    }        private static void browseNode(OpcUaClient client, UaNode uaNode) throws Exception {        List<? extends UaNode> nodes;        if (uaNode == null) {            nodes = client.getAddressSpace().browseNodes(Identifiers.ObjectsFolder);        } else {            nodes = client.getAddressSpace().browseNodes(uaNode);        }        for (UaNode nd : nodes) {            //排除系统行性节点,这些系统性节点名称一般都是以"_"开头            if (Objects.requireNonNull(nd.getBrowseName().getName()).contains("_")) {                continue;            }            System.out.println("Node= " + nd.getBrowseName().getName());            browseNode(client, nd);        }    }        private static void readNode(OpcUaClient client) throws Exception {        int namespaceIndex = 2;        String identifier = "通道 1.设备 1.标记 1";        //节点        NodeId nodeId = new NodeId(namespaceIndex, identifier);        //读取节点数据        DataValue value = client.readValue(0.0, TimestampsToReturn.Neither, nodeId).get();        //标识符        System.out.println(identifier + ": " + String.valueOf(value.getValue().getValue()));    }        private static void writeNodeValue(OpcUaClient client) throws Exception {        //节点        NodeId nodeId = new NodeId(2, "通道 1.设备 1.标记 1");        short i = 3;        //创建数据对象,此处的数据对象一定要定义类型,不然会出现类型错误,导致无法写入        DataValue nowValue = new DataValue(new Variant(i), null, null);        //写入节点数据        StatusCode statusCode = client.writeValue(nodeId, nowValue).join();        System.out.println("结果:" + statusCode.isGood());    }}

模拟数据进行代码测试

OPC-DA 代码验证

使用 KEPServerEX 6 作为 OPC-Server 进行测试,百度网盘下载链接如下:

链接:https://pan.baidu.com/s/1pigppR62xTsE_4ecXx9m8Q?pwd=3aig 提取码:3aig

在界面上可以右键单击标记名称进行数据格式的设置

在这里插入图片描述
单击工具栏最后一个,创建一个 OPC Quick client,可以观察到,此时通道 1.设备 1.标记 2的值为 0

在这里插入图片描述
修改 opc-da 写入程序,写入数值为 300

在这里插入图片描述
执行写入程序,查看 client 中的对应值,写入成功

在这里插入图片描述
使用读取程序对数据进行读取,同样可以读取到对应的数值

在这里插入图片描述

OPC-UA 代码验证

在验证之前首先右键项目,选择属性,修改 OPC-UA 属性中的”允许匿名登录“为是

在这里插入图片描述

配置写入数据的方法,将对应的数值从 300 修改为 3

在这里插入图片描述

执行代码,查看输出结果

在这里插入图片描述

来源地址:https://blog.csdn.net/zqf787351070/article/details/128275537

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯