package com.jcdm.main.da.opcuaconfig.client; import com.google.common.collect.ImmutableList; import com.jcdm.main.da.opcuaconfig.domain.DaOpcuaConfig; import com.jcdm.main.da.opcuaconfig.domain.NodeEntity; import com.jcdm.main.da.opcuaconfig.service.IDaOpcuaConfigService; import lombok.extern.slf4j.Slf4j; import org.eclipse.milo.opcua.sdk.client.OpcUaClient; import org.eclipse.milo.opcua.sdk.client.api.nodes.VariableNode; import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription; import org.eclipse.milo.opcua.stack.core.AttributeId; import org.eclipse.milo.opcua.stack.core.BuiltinDataType; import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue; import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId; import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode; import org.eclipse.milo.opcua.stack.core.types.builtin.Variant; import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned; import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode; import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn; import org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemCreateRequest; import org.eclipse.milo.opcua.stack.core.types.structured.MonitoringParameters; import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutionException; /** * @ClassName: ClientHandler * @Description: 客户端处理 * @author Jellyleo * @date 2019年12月12日 */ @Slf4j @Service public class ClientHandler { // 客户端实例 public static OpcUaClient client = null; public List b = null; @Autowired private ClientRunner clientRunner; @Autowired private IDaOpcuaConfigService daOpcuaConfigService; /** * * @MethodName: connect * @Description: connect * @throws Exception * @CreateTime 2019年12月18日 上午10:41:09 */ public String connect() throws Exception { if (client != null) { return "客户端已创建"; } client = clientRunner.run(); if (client == null) { return "客户端配置实例化失败"; } // 创建连接 client.connect().get(); return "创建连接成功"; } /** * @MethodName: disconnect * @Description: 断开连接 * @return * @throws Exception * @CreateTime 2019年12月18日 上午10:45:21 */ public String disconnect() throws Exception { if (client == null) { return "连接已断开"; } // 断开连接 clientRunner.getFuture().complete(client); client = null; return "断开连接成功"; } /** * @MethodName: subscribe * @Description: 订阅节点变量 * @throws Exception * @CreateTime 2019年12月18日 上午10:38:11 */ public String subscribe(List nodes) throws Exception { if (client == null) { return "找不到客户端,操作失败"; } // 查询订阅对象,没有则创建 UaSubscription subscription = null; ImmutableList subscriptionList = client.getSubscriptionManager().getSubscriptions(); if (CollectionUtils.isEmpty(subscriptionList)) { subscription = client.getSubscriptionManager().createSubscription(1000.0).get(); } else { subscription = subscriptionList.get(0); } // 监控项请求列表 List requests = new ArrayList<>(); if (!CollectionUtils.isEmpty(nodes)) { for (NodeEntity node : nodes) { // 创建监控的参数 MonitoringParameters parameters = new MonitoringParameters(subscription.nextClientHandle(), 1000.0, // sampling // interval null, // filter, null means use default Unsigned.uint(10), // queue size true // discard oldest ); // 创建订阅的变量, 创建监控项请 求 MonitoredItemCreateRequest request = new MonitoredItemCreateRequest( new ReadValueId(new NodeId(node.getIndex(), node.getIdentifier()), AttributeId.Value.uid(), null, null), MonitoringMode.Reporting, parameters); requests.add(request); } } // 创建监控项,并且注册变量值改变时候的回调函数 subscription.createMonitoredItems(TimestampsToReturn.Both, requests, (item, id) -> { item.setValueConsumer((i, v) -> { handle(i.getReadValueId().getNodeId(), v.getValue()); }); }).get(); return "订阅成功"; } /** * * @MethodName: write * @Description: 回调函数 * @CreateTime 2023年10月13日 */ public void handle(NodeId id, Variant value){ if (b == null || 0 > b.size()) { DaOpcuaConfig opcuaConfParam=new DaOpcuaConfig(); opcuaConfParam.setSubscribe("Y"); b=daOpcuaConfigService.selectDaOpcuaConfigList(opcuaConfParam); } //使用Stream API在List中查找元素 DaOpcuaConfig daOpcuaConfig = b.stream() .filter(customer ->id.getIdentifier().toString().equals(customer.getNode())) .findAny() .orElse(null); try { Class clazz = Class.forName("com.jcdm.main.da.opcuaconfig.cert.MethodName"); Method method = clazz.getMethod(daOpcuaConfig.getrFunction(), new Class[] { String.class, String.class }); method.invoke(clazz.newInstance(),new Object[] { new String(id.getIdentifier().toString()), new String(value.getValue().toString()) }); } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { e.printStackTrace(); } } /** * @MethodName: write * @Description: 变节点量写入 * @param node * @throws Exception * @CreateTime 2019年12月18日 上午9:51:40 */ public static Boolean write(NodeEntity node) throws Exception { if (client == null) { log.info("找不到客户端,操作失败"); return false; } NodeId nodeId = new NodeId(node.getIndex(), node.getIdentifier()); Variant value = null; switch (node.getType()) { case "int": value = new Variant(Integer.parseInt(node.getValue().toString())); break; case "boolean": value = new Variant(Boolean.parseBoolean(node.getValue().toString())); break; case "short": value = new Variant(Short.parseShort(node.getValue().toString())); break; case "long": value = new Variant(Long.parseLong(node.getValue().toString())); break; case "string": value = new Variant(node.getValue().toString()); break; case "char": value = new Variant(node.getValue().toString().charAt(0)); break; } DataValue dataValue = new DataValue(value, null, null); StatusCode statusCode = client.writeValue(nodeId, dataValue).get(); return statusCode.isGood(); } /** * 方法描述: 读取多个点位的值 * * @param nodeIdList 点位集合 * @return {@link List} * @throws */ public static List readValues(List nodeIdList){ try { List dataValues=client.readValues(0.0, TimestampsToReturn.Both,nodeIdList).get(); return dataValues; } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } return null; } /** * @MethodName: read * @Description: 读取 * @param node * @return * @throws Exception * @CreateTime 2019年12月19日 下午2:40:34 */ public String read(NodeEntity node) throws Exception { if (client == null) { return "找不到客户端,操作失败"; } NodeId nodeId = new NodeId(node.getIndex(), node.getIdentifier()); VariableNode vnode = client.getAddressSpace().createVariableNode(nodeId); DataValue value = vnode.readValue().get(); log.info("Value={}", value); Variant variant = value.getValue(); log.info("Variant={}", variant.getValue()); log.info("BackingClass={}", BuiltinDataType.getBackingClass(variant.getDataType().get())); return variant.getValue().toString(); } /** * 方法描述: 写入多个节点的值 * * @param keys 节点集合 * @param values 值集合 * @param client 客户端 * @return {@link Object} * @throws */ public static Object writeValues(Set keys, List values, OpcUaClient client){ List nodeIs=new ArrayList<>(keys.size()); keys.forEach(e->{ NodeId nodeId = new NodeId(2, e); nodeIs.add(nodeId); }); List dataValues=new ArrayList<>(values.size()); values.forEach(e->{ Variant value=new Variant(Double.parseDouble(e.toString())); DataValue dataValue=new DataValue(value); dataValues.add(dataValue); }); try { client.writeValues(nodeIs,dataValues).get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } return null; } }