package cn.stylefeng.guns.opcua.client; import cn.stylefeng.guns.opcua.controller.OpcuaConfController; import cn.stylefeng.guns.opcua.model.params.OpcuaConfParam; import cn.stylefeng.guns.opcua.model.result.OpcuaConfResult; import com.google.common.collect.ImmutableList; import cn.stylefeng.guns.opcua.entity.NodeEntity; 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 cn.stylefeng.guns.base.enums.MicroTimestamp; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * @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 OpcuaConfController opcuaConfController; /** * * @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) -> { handle2(i.getReadValueId().getNodeId(), v.getValue()); }); }).get(); return "订阅成功"; } /** * * @MethodName: write * @Description: 回调函数 * @CreateTime 2023年10月13日 */ /*public void handle(NodeId id, Variant value){ long startTime = System.currentTimeMillis(); OpcuaConfParam opcuaConfParam=new OpcuaConfParam(); opcuaConfParam.setNode(id.getIdentifier().toString()); List a=opcuaConfController.mylist(opcuaConfParam); log.info("数据库访问代码执行时间:" + (System.currentTimeMillis() - startTime) + "毫秒"); String str1 = id.getIdentifier().toString()+":"+value.getValue().toString(); try { Class clazz = Class.forName(a.get(0).getRModule()); Method method = clazz.getMethod(a.get(0).getRFunction(), String.class); method.invoke(clazz.newInstance(), str1); } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { e.printStackTrace(); } log.info("代码执行时间:" + (System.currentTimeMillis() - startTime) + "毫秒"); }*/ public void handle2(NodeId id, Variant value){ MicroTimestamp t = null; String sTime=t.INSTANCE.get(); if (b == null || 0 > b.size()) { OpcuaConfParam opcuaConfParam=new OpcuaConfParam(); opcuaConfParam.setSubscribe(1); b=opcuaConfController.mylist(opcuaConfParam); } //使用Stream API在List中查找元素 OpcuaConfResult opcuaConfResult = b.stream() .filter(customer ->id.getIdentifier().toString().equals(customer.getNode())) .findAny() .orElse(null); try { Class clazz = Class.forName(opcuaConfResult.getRModule()); Method method = clazz.getMethod(opcuaConfResult.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(); } log.info("代码执行开始时间为:"+ sTime +",结束时间为:"+t.INSTANCE.get()+"."); } /** * @MethodName: write * @Description: 变节点量写入 * @param node * @throws Exception * @CreateTime 2019年12月18日 上午9:51:40 */ public String write(NodeEntity node) throws Exception { if (client == null) { return "找不到客户端,操作失败"; } 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 "long": value = new Variant(Long.parseLong(node.getValue().toString())); break; } DataValue dataValue = new DataValue(value, null, null); StatusCode statusCode = client.writeValue(nodeId, dataValue).get(); return "节点【" + node.getIdentifier() + "】写入状态:" + statusCode.isGood(); } /** * @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 "节点【" + node.getIdentifier() + "】:" + variant.getValue(); } }