Java与opc通信之一 - opc ua(milo)

这篇文章介绍如何使用opc ua的方式,访问opc数据。

1、引入依赖

<!-- milo连接opc -->
        <dependency>
            <groupId>org.eclipse.milo</groupId>
            <artifactId>sdk-client</artifactId>
            <version>0.6.8</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.milo</groupId>
            <artifactId>sdk-server</artifactId>
            <version>0.6.8</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.milo</groupId>
            <artifactId>dictionary-reader</artifactId>
            <version>0.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.milo</groupId>
            <artifactId>dictionary-manager</artifactId>
            <version>0.6.0</version>
        </dependency>
View Code

2、初始化opc ua客户端

@Component
public class ClientGen {
    //加载加密类型
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
    private final Logger log = LoggerFactory.getLogger(getClass());

    // milo用来连接opc ua的client
    public static OpcUaClient opcUaClient;

    @Autowired
    private OpcUaConfig opcUaConfig;

    /**
     *  创建opc ua客户端(在项目启动的时候执行该方法)
     *
     */
    @PostConstruct
    public void createClient_() throws UaException {
        String endPoint = opcUaConfig.getEndpointUrl();
        opcUaClient = OpcUaClient.create(
                endPoint,
                endpointDescriptions -> {
                    final List<EndpointDescription> collect = endpointDescriptions.stream().collect(Collectors.toList());
                    final Optional<EndpointDescription> first = endpointDescriptions
                            .stream()
                            .findFirst();
                    System.out.println(first.get().getSecurityPolicyUri());
                    return Optional.of(collect.get(0));
                },
                configBuilder ->
                        configBuilder
                                .setApplicationName(LocalizedText.english("opc-ua client"))
                                .setApplicationUri(endPoint)
//                                .setIdentityProvider(new UsernameProvider(username, password))
                                .setIdentityProvider(new AnonymousProvider())
                                .setRequestTimeout(uint(5000))
                                .build()
        );
        log.info("创建客户端:{} 成功!", opcUaClient);

    }

    /**
     *  创建opc ua客户端(在项目启动的时候执行该方法)
     *
     */

    public void createClient(){
        try {
            Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
            Files.createDirectories(securityTempDir);
            if (!Files.exists(securityTempDir)) {
                throw new Exception("没有创建安全目录: " + securityTempDir);
            }
            log.info("安全目录: {}", securityTempDir.toAbsolutePath());
            //加载秘钥
            KeyStoreLoader loader = new KeyStoreLoader().load(securityTempDir);
            //安全策略 None、Basic256、Basic128Rsa15、Basic256Sha256
            SecurityPolicy securityPolicy = SecurityPolicy.None;
            List<EndpointDescription> endpoints;
            try {
                endpoints = DiscoveryClient.getEndpoints(opcUaConfig.getEndpointUrl()).get();

            } catch (Throwable ex) {
                String discoveryUrl = opcUaConfig.getEndpointUrl();
                if (!discoveryUrl.endsWith("/")) {
                    discoveryUrl += "/";
                }
                discoveryUrl += "discovery";

                log.info("开始连接 URL: {}", discoveryUrl);
                endpoints = DiscoveryClient.getEndpoints(discoveryUrl).get();
            }
            EndpointDescription endpoint = endpoints.stream()
                    .filter(e -> e.getEndpointUrl().equals(opcUaConfig.getEndpointUrl()))
                    .findFirst().orElseThrow(() -> new Exception("没有节点返回"));
                    //.filter(e -> e.getSecurityPolicyUri().equals(securityPolicy.getUri()))
                    //.filter(opcUaConfig.endpointFilter())
                    //.findFirst()
                    //.orElseThrow(() -> new Exception("没有连接上端点"));
            log.info("使用端点: {} [{}/{}]", endpoint.getEndpointUrl(), securityPolicy, endpoint.getSecurityMode());
            OpcUaClientConfig config = OpcUaClientConfig.builder()
                    .setApplicationName(LocalizedText.english("eclipse milo opc-ua client"))
                    .setApplicationUri("urn:eclipse:milo:examples:client")
                    .setCertificate(loader.getClientCertificate()) // 证书
                    .setKeyPair(loader.getClientKeyPair())
                    .setEndpoint(endpoint)
                    //根据匿名验证和第三个用户名验证方式设置传入对象 AnonymousProvider(匿名方式)UsernameProvider(账户密码)
                    .setIdentityProvider(new AnonymousProvider())
                    .setRequestTimeout(uint(100000000))
                    .build();
            opcUaClient = OpcUaClient.create(config);
            log.info("创建客户端:{} 成功!", opcUaClient);
        } catch (Exception e) {
            log.error("创建客户端失败" + e.getMessage());
        }
    }
}
View Code

3、批量采集opc实时数据

/**
     * 采集一标段和二标段的数据
     */
    private List<DbBlockDto> gatherSectionOneData(List<NodeId> nodeIds) throws ExecutionException, InterruptedException {
        List<DbBlockDto> dtoList = new ArrayList<>();
        // 获取opc ua客户端
        OpcUaClient client = ClientGen.opcUaClient;
        log.info("client is: {}", client);
        // 链接opc ua
        client.connect().get();
        // 批量采集数据
        final CompletableFuture<List<DataValue>> data = client.readValues(0d, TimestampsToReturn.Neither, nodeIds);
        List<DataValue> dataValues = data.get();
        if (dataValues == null) {
            return dtoList;
        }
        // 封装数据
        for (int i = 0; i < dataValues.size(); i++) {
            DbBlockDto dbBlockDto = new DbBlockDto();
            DataValue value = dataValues.get(i);
            dbBlockDto.setName(nodeIds.get(i).getIdentifier().toString().substring(2));
            // 校验数据
            if(value.getStatusCode() != null){
                if (value.getStatusCode().isGood()) {
                    String plcValue = value.getValue().getValue().toString();
                    dbBlockDto.setValue(plcValue);
                }
            }
            dtoList.add(dbBlockDto);
        }
        return dtoList;
    }
View Code

注:1、读取数据时,需要将业务变量名称封装成 “t|业务字段”的形式

// 将二标段DB块的变量名称,拼接成t|xxx的格式
            blocks.parallelStream().forEach(n -> n.setName("t|" + n.getName()));
            List<NodeId> nodeIdList = new ArrayList<>();
            for(DbBlock dbBlock : blocks){
                NodeId nodeId = new NodeId(1, dbBlock.getName());
                nodeIdList.add(nodeId);
            }

2、本机的host文件需要配置为opc服务器的服务地址

public String getEndpointUrl() {
        return "opc.tcp://XmcWinCCServer:4862";
    }

 

源码:https://gitee.com/caesarthegreat/opc.git

posted @ 2023-01-29 10:28  Caesar_the_great  阅读(3824)  评论(0编辑  收藏  举报