本次采用KEPServerEX6模拟服务端,使用milo开发的程序作为客户端
一、Milo库
本文使用Milo库实现OPC UA客户端,以达到通过java读、写、订阅变量的目的。
官网:https://github.com/eclipse/milo
二、JAVA连接OPCUA客户端
- pom添加依赖
<dependency> <groupId>org.eclipse.milo</groupId> <artifactId>sdk-server</artifactId> <version>0.2.4</version> </dependency> <dependency> <groupId>org.eclipse.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>
- 安全策略
对应的OPC UA服务地址(也就是上面定义的字符串)的节点并不止一个,因为在一个对应的OPC UA服务地址里面可能也有不一样的服务器安全策略,每种不同安全策略对应一个节点。
无安全设置
Basic128Rsa15 - 签名
Basic128Rsa15 - 签名和加密
Basic256 - 签名
Basic256 - 签名和加密
Basic256Sha256 - 签名
Basic256Sha256 - 签名和加密 - 创建客户端
public static OpcUaClient creatClient() { try { // 连接地址端口号 String EndPointUrl = "opc.tcp://192.168.1.120:49320"; //安全策略选择 EndpointDescription[] endpointDescription = UaTcpStackClient.getEndpoints(EndPointUrl).get(); //过滤掉不需要的安全策略,选择一个自己需要的安全策略 EndpointDescription endpoint = Arrays.stream(endpointDescription) .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.NONE)) .findFirst().orElseThrow(() -> new Exception("no desired endpoints returned")); OpcUaClientConfig config = OpcUaClientConfig.builder() .setApplicationName(LocalizedText.english("test")) // opc ua 定义的名 .setApplicationUri(EndPointUrl)// 地址 .setEndpoint(endpoint)// 安全策略等配置 .setIdentityProvider(new UsernameProvider("username", "password")) .setRequestTimeout(UInteger.valueOf(50000)) //等待时间 .build(); OpcUaClient opcClient = new OpcUaClient(config);// 准备连接 return opcClient; } catch (Exception e) { e.printStackTrace(); } return null; }
- 读取节点数据
public static void readValue(OpcUaClient client) { try { NodeId nodeId = new NodeId(2, "通道 1.设备 1.ua1");//int DataValue value = client.readValue(0.0, TimestampsToReturn.Both, nodeId).get(); System.out.println("=====读取ua1====:" + value.getValue().getValue()); } catch (Exception e) { e.printStackTrace(); } }
- 写入节点数据
public static void writeValue(OpcUaClient client) { try { //创建变量节点 NodeId nodeId = new NodeId(2, "通道 1.设备 1.ua3"); //uda3 boolean boolean value = true; //创建Variant对象和DataValue对象 Variant v = new Variant(value); DataValue dataValue = new DataValue(v, null, null); StatusCode statusCode = client.writeValue(nodeId, dataValue).get(); System.out.println(statusCode); System.out.println("=====写入ua1====:" +statusCode.isGood()); } catch (Exception e) { e.printStackTrace(); } }
- 订阅
private static void subscribe(OpcUaClient client) throws Exception { //创建发布间隔1000ms的订阅对象 client.getSubscriptionManager() .createSubscription(1000.0) .thenAccept(t -> { //节点 NodeId nodeId = new NodeId(2, "通道 1.设备 1.ua1"); ReadValueId readValueId = new ReadValueId(nodeId, AttributeId.Value.uid(), null, null); //创建监控的参数 MonitoringParameters parameters = new MonitoringParameters(UInteger.valueOf(1), 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); }
订阅成功后,main线程会被阻塞,修改OPC UA中的变量值后,就可以即时查看到订阅的消息。订阅时间可以通过修改
Thread.sleep
的沉睡时间实现。 - main测试
public static void main(String[] args) { try { //创建OPC UA客户端 OpcUaClient opcUaClient = creatClient(); //创建连接 opcUaClient.connect().get(); //读取 readValue(opcUaClient); //写入 writeValue(opcUaClient); //订阅 subscribe(opcUaClient); //关闭连接 opcUaClient.disconnect().get(); } catch (Exception e) { e.printStackTrace(); } }
- 运行结果