package com.jcdm.main.da.opcuaconfig.client;
|
|
import com.google.common.collect.ImmutableList;
|
import com.jcdm.main.da.opcuaconfig.controller.DaOpcuaConfigController;
|
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<DaOpcuaConfig> 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<NodeEntity> nodes) throws Exception {
|
|
if (client == null) {
|
return "找不到客户端,操作失败";
|
}
|
|
// 查询订阅对象,没有则创建
|
UaSubscription subscription = null;
|
ImmutableList<UaSubscription> subscriptionList = client.getSubscriptionManager().getSubscriptions();
|
if (CollectionUtils.isEmpty(subscriptionList)) {
|
subscription = client.getSubscriptionManager().createSubscription(1000.0).get();
|
} else {
|
subscription = subscriptionList.get(0);
|
}
|
|
// 监控项请求列表
|
List<MonitoredItemCreateRequest> 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(1L);
|
b=daOpcuaConfigService.selectDaOpcuaConfigList(opcuaConfParam);
|
}
|
//使用Stream API在List<T>中查找元素
|
DaOpcuaConfig daOpcuaConfig = b.stream()
|
.filter(customer ->id.getIdentifier().toString().equals(customer.getNode()))
|
.findAny()
|
.orElse(null);
|
try {
|
Class<?> clazz = Class.forName(daOpcuaConfig.getrModule());
|
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 keys 点位集合
|
* @return {@link List<DataValue>}
|
* @throws
|
*/
|
// public static List<DataValue> readValues2(Set<String> keys){
|
// List<NodeId> nodeIdList=new ArrayList<>(500);
|
// keys.forEach(e->{
|
// NodeId nodeId = new NodeId(2, e);
|
// nodeIdList.add(nodeId);
|
// });
|
// try {
|
// List<DataValue> dataValues=client.readValues(0.0, TimestampsToReturn.Both,nodeIdList).get();
|
// return dataValues;
|
// } catch (InterruptedException | ExecutionException e) {
|
// e.printStackTrace();
|
// }
|
// return null;
|
// }
|
|
|
/**
|
* 方法描述: 读取多个点位的值
|
*
|
* @param nodeIdList 点位集合
|
* @return {@link List<DataValue>}
|
* @throws
|
*/
|
public static List<DataValue> readValues(List<NodeId> nodeIdList){
|
try {
|
List<DataValue> 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<String> keys, List<Object> values, OpcUaClient client){
|
List<NodeId> nodeIs=new ArrayList<>(keys.size());
|
keys.forEach(e->{
|
NodeId nodeId = new NodeId(2, e);
|
nodeIs.add(nodeId);
|
});
|
List<DataValue> 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;
|
}
|
}
|