java 整合opc读取

参考链接

opc 介绍 软件 参考链接

创建opc ua 连接错误 参考连接

前置条件

下载 KEPServer V6 测试 参考连接有地址,这里摘抄下

项目使用KEPServer V6(427M,中文):百度网盘 ,密码: ykj2

软件操作

下载完 KEPServer V6 打开
界面如下 Default User 是默认用户名 点击连接
在这里插入图片描述
连接成功后点击 通道 1 设备 1 可以看到默认配置的信息
在这里插入图片描述
如果使用 Opc Ua 无密码登录,需要配置opc属性
右键点击项目,点击属性

在这里插入图片描述
选择 opc UA 选择允许匿名登录
在这里插入图片描述
配置完毕 点击应用 确定

配置Opc UA服务端属性
在这里插入图片描述
选择仅主机
在这里插入图片描述

点击客户端 查看数据
在这里插入图片描述

启动测试类 看看有没有消息

opc介绍

ocp连接可分为uada模式

ua 连接

添加依赖 这里使用 miilo 依赖

 <properties>     
        <miilo.version>0.6.9</miilo.version>
    </properties>
<dependency>
     <groupId>org.eclipse.milo</groupId>
     <artifactId>sdk-client</artifactId>
     <version>${miilo.version}</version>
 </dependency>
<!--Milo服务端的依赖-->
 <dependency>
     <groupId>org.eclipse.milo</groupId>
     <artifactId>sdk-server</artifactId>
     <version>${miilo.version}</version>
 </dependency>
 <dependency>
     <groupId>org.bouncycastle</groupId>
     <artifactId>bcpkix-jdk15on</artifactId>
     <version>1.57</version>
 </dependency>

创建客户端

创建客户端并测试

  
@Slf4j
public class OpcUaClientTest {

    private static AtomicInteger atomic = new AtomicInteger(1);
    // 定义服务端地址
    private final static String endPointUrl = "opc.tcp://127.0.0.1:49320";

    public static void main(String[] args) throws Exception {
        //创建OPC UA客户端
        OpcUaClient opcUaClient = createClient();

        //开启连接
        opcUaClient.connect().get();

        //遍历节点
        browseNode(opcUaClient, null);

        //读
        readNode(opcUaClient);

        //写
        writeNodeValue(opcUaClient);

        //订阅
        subscribe(opcUaClient);

        //批量订阅
        //managedSubscriptionEvent(opcUaClient);

        //关闭连接
        opcUaClient.disconnect().get();
    }



    /**
     * 订阅(单个)
     *
     * @param client
     * @throws Exception
     */
    private static void subscribe(OpcUaClient client) throws Exception {
        //创建发布间隔1000ms的订阅对象
        client
                .getSubscriptionManager()
                .createSubscription(1000.0)
                .thenAccept(t -> {
                    //节点
                    NodeId nodeId = new NodeId(2, "TD-01.SB-01.AG-01");
                    ReadValueId readValueId = new ReadValueId(nodeId, AttributeId.Value.uid(), null, null);
                    //创建监控的参数
                    MonitoringParameters parameters = new MonitoringParameters(UInteger.valueOf(atomic.getAndIncrement()), 1000.0, null, UInteger.valueOf(10), true);
                    //创建监控项请求
                    //该请求最后用于创建订阅。
                    MonitoredItemCreateRequest request = new MonitoredItemCreateRequest(readValueId, MonitoringMode.Reporting, parameters);
                    List<MonitoredItemCreateRequest> requests = new ArrayList<>();
                    requests.add(request);
                    //创建监控项,并且注册变量值改变时候的回调函数。
                    t.createMonitoredItems(
                            TimestampsToReturn.Both,
                            requests,
                            (item, id) -> item.setValueConsumer((it, val) -> {
                                System.out.println("nodeid :" + it.getReadValueId().getNodeId());
                                System.out.println("value :" + val.getValue().getValue());
                            })
                    );
                }).get();

        //持续订阅
        Thread.sleep(Long.MAX_VALUE);
    }

    /**
     * 写入节点数据
     *
     * @param client
     * @throws Exception
     */
    private static void writeNodeValue(OpcUaClient client) throws Exception {
        //节点
        NodeId nodeId = new NodeId(2, "TD-01.SB-01.AG-01");
        short i = 3;
        //创建数据对象,此处的数据对象一定要定义类型,不然会出现类型错误,导致无法写入
        DataValue nowValue = new DataValue(new Variant(i), null, null);
        //写入节点数据
        StatusCode statusCode = client.writeValue(nodeId, nowValue).join();
        System.out.println("结果:" + statusCode.isGood());
    }



    /**
     * 读取节点数据
     *
     * @param client OPC UA客户端
     * @throws Exception
     */
    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();
        //标识符
        identifier = String.valueOf(nodeId.getIdentifier());
        log.info("读取数据" + identifier + ": " + String.valueOf(value.getValue().getValue()));
    }


    /**
     * 遍历树形节点
     *
     * @param client OPC UA客户端
     * @param uaNode 节点
     * @throws Exception
     */
    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);
        }
    }



    /**
     * 创建OPC UA客户端
     * @return
     * @throws Exception
     */
    private static OpcUaClient createClient() throws Exception {
        //opc ua服务端地址
        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
        Files.createDirectories(securityTempDir);
        if (!Files.exists(securityTempDir)) {
            throw new Exception("unable to create security dir: " + securityTempDir);
        }
        return OpcUaClient.create(endPointUrl, endpoints ->
                       final Optional<EndpointDescription> endpoint = endpoints
                                .stream()
                                .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
                                .findFirst();
                        EndpointDescription newEndpoint=new EndpointDescription(endPointUrl, endpoint.get().getServer(), endpoint.get().getServerCertificate(),
                                endpoint.get().getSecurityMode(),endpoint.get().getSecurityPolicyUri(),endpoint.get().getUserIdentityTokens(),
                                endpoint.get().getTransportProfileUri(), endpoint.get().getSecurityLevel());
                        return Optional.of(newEndpoint);
                configBuilder ->
                        configBuilder
                                .setApplicationName(LocalizedText.english("eclipse milo opc-ua client"))
                                .setApplicationUri("urn:eclipse:milo:examples:client")
                                //访问方式
                                .setIdentityProvider(new AnonymousProvider())
                                .setRequestTimeout(UInteger.valueOf(5000))
                                .build()
        );
    }
}

创建连接时得使用这个,不然连接错误 参考连接

 final Optional<EndpointDescription> endpoint = endpoints
                                .stream()
                                .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
                                .findFirst();
                        EndpointDescription newEndpoint=new EndpointDescription(endPointUrl, endpoint.get().getServer(), endpoint.get().getServerCertificate(),
                                endpoint.get().getSecurityMode(),endpoint.get().getSecurityPolicyUri(),endpoint.get().getUserIdentityTokens(),
                                endpoint.get().getTransportProfileUri(), endpoint.get().getSecurityLevel());
                        return Optional.of(newEndpoint);

线上代码参考

package com.ruoyi.business.opc.config;

import com.google.common.collect.Maps;
import com.ruoyi.business.domain.BizOpcInfo;
import com.ruoyi.business.mapper.BizOpcLogMapper;
import com.ruoyi.business.opc.util.OpcDataUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.UaClient;
import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
import org.eclipse.milo.opcua.sdk.client.model.nodes.objects.ServerTypeNode;
import org.eclipse.milo.opcua.sdk.client.nodes.UaNode;
import org.eclipse.milo.opcua.stack.core.Identifiers;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.*;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author 
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class OpcUaConfig {
    public static UaClient opcLink = null;

    private static final Logger logger = LoggerFactory.getLogger("sys-commun");
    private final OpcDataUtils opcDataUtils;
	// 将打开的opc客户端放在map中  防止重复打开
    public final static Map<String, UaClient> OPC_MAP = Maps.newHashMap();
    /**
     * 创建订阅
     * opc ua  打开连接订阅
     * res  是否需要重复连接
     *
     * @param info 信息
     */
    public void createSubscription(BizOpcInfo info) {
        try {
            //等待三秒(可要可不要)
            Thread.sleep(3 * 1000);
            UaClient uaClient = null;

            Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
            Files.createDirectories(securityTempDir);
            if (!Files.exists(securityTempDir)) {
                throw new Exception("unable to create security dir: " + securityTempDir);
            }
            String endPointUrl = info.getOpcUrl();
            OpcUaClient opcClient =  OpcUaClient.create(endPointUrl,
                    endpoints -> {
                        final Optional<EndpointDescription> endpoint = endpoints
                                .stream()
                                .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
                                .findFirst();
                        EndpointDescription newEndpoint=new EndpointDescription(endPointUrl, endpoint.get().getServer(), endpoint.get().getServerCertificate(),
                                endpoint.get().getSecurityMode(),endpoint.get().getSecurityPolicyUri(),endpoint.get().getUserIdentityTokens(),
                                endpoint.get().getTransportProfileUri(), endpoint.get().getSecurityLevel());
                        return Optional.of(newEndpoint);
                    },
                    configBuilder ->
                            configBuilder
                                    .setApplicationName(LocalizedText.english("eclipse milo opc-ua client"))
                                    .setApplicationUri("urn:eclipse:milo:examples:client")
                                    //访问方式
                                    .setIdentityProvider(new AnonymousProvider())
                                    .setRequestTimeout(UInteger.valueOf(50000))
                                    .build()
            );
            uaClient = opcClient.connect().get();
            if (opcLink == null){
                opcLink = uaClient;
                OPC_MAP.put(endPointUrl, uaClient);
            }else {
                uaClient.disconnect().get();         
            }
            logger.info(String.format("opc链接%s打开成功", info.getOpcUrl()));
        } catch (Exception e) {
            logger.error(String.format("opc链接%s打开失败", info.getOpcUrl()));
            // 保存错误日志
            opcDataUtils.saveError(info, e);
        }
    }




    public static List<? extends UaNode> browseNode(UaNode uaNode) throws Exception {
        List<? extends UaNode> nodes;
        if (uaNode == null) {
            nodes = opcLink.getAddressSpace().browseNodes(Identifiers.ObjectsFolder);
        } else {
            nodes = opcLink.getAddressSpace().browseNodes(uaNode);
        }
        nodes = nodes.stream().filter(t->!(t instanceof ServerTypeNode || t.getBrowseName().getName().startsWith("_"))).collect(Collectors.toList());
        return nodes;
    }

    /**
     * 读取节点数据
     *
     * @throws Exception
     */
    public static Object readNode(String key) throws Exception {
        int namespaceIndex = 2;
        //节点
        NodeId nodeId = new NodeId(namespaceIndex, key);
        //读取节点数据
        DataValue value = opcLink.readValue(0.0, TimestampsToReturn.Neither, nodeId).get();
        //标识符
        String identifier1 = String.valueOf(nodeId.getIdentifier());
        return value.getValue().getValue();
    }

    /**
     * 写入节点数据
     *
     * @param client
     * @throws Exception
     */
    public static boolean writeNodeValue(UaClient client,String key ,String value,String valueType) {
        //节点
        NodeId nodeId = new NodeId(2, key);
        //创建数据对象,此处的数据对象一定要定义类型,不然会出现类型错误,导致无法写入
        Object v = value;
        switch (valueType){
            case "short":
                v = Short.valueOf(value);
                break;
            case "int":
            case "long":
                v = Integer.valueOf(value);
                break;
            case "float":
                v = Float.valueOf(value);
                break;
            case "double":
                v = Double.valueOf(value);
                break;
            case "bool":
                v = value.equals("1")? Boolean.valueOf("true"):Boolean.valueOf("false");
                break;
            case "string":
                v = String.valueOf(value);
                break;
            case "word":
                v = Unsigned.ushort(value);
                break;
            default:
                v = String.valueOf(v);
                break;
        }
        DataValue nowValue = new DataValue(new Variant(v), null, null);
        //写入节点数据
        StatusCode statusCode = client.writeValue(nodeId, nowValue).join();
        return statusCode.isGood();
    }

    public Boolean exist(List<String> list1, List<String> list2) {
        Collections.sort(list1);
        Collections.sort(list2);
        return list1.equals(list2);
    }
}

异常

  1. Thread.sleep(2000); // 让子弹飞一会
    UaException: status=Bad_SessionClosed, message=The session was closed by the client.

原因分析: opcUaClient.connect().get(); 是一个异步的过程,可能在读写的时候,连接还没有创建好。

解决方法: Thread.sleep(2000); // 线程休眠一下再返回对象,给创建过程一个时间。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值