1、客户端依赖包
<dependency>
<groupId>org.eclipse.milo</groupId>
<artifactId>sdk-client</artifactId>
<version>0.2.4</version>
</dependency>
具体实现
package com.water.chlorine.utils;
import com.water.chlorine.WaterChlorineApplication;
import com.water.chlorine.entity.DictCode;
import com.water.chlorine.mapper.DictCodeMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig;
import org.eclipse.milo.opcua.sdk.client.api.nodes.Node;
import org.eclipse.milo.opcua.sdk.client.nodes.UaNode;
import org.eclipse.milo.opcua.stack.client.UaTcpStackClient;
import org.eclipse.milo.opcua.stack.core.Identifiers;
import org.eclipse.milo.opcua.stack.core.UaException;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.*;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseDirection;
import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseResultMask;
import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseDescription;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseResult;
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
import org.eclipse.milo.opcua.stack.core.types.structured.ReferenceDescription;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.Identifiers;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseDirection;
import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseResultMask;
import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseDescription;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseResult;
import org.eclipse.milo.opcua.stack.core.types.structured.ReferenceDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.ushort;
import static org.eclipse.milo.opcua.stack.core.util.ConversionUtil.toList;
import static org.python.icu.math.MathContext.ROUND_HALF_UP;
@Slf4j
@Data
@Component
public class OpcUtil {
public static OpcUaClient opcClient = null;
/**
* 开启 opc请求对象
*
* @return opc请求对象
*/
public static OpcUaClient createOpcClient() throws Exception {
//
DictCodeMapper dictCodeMapper = WaterChlorineApplication.ac.getBean(DictCodeMapper.class);
DictCode dictCode = dictCodeMapper.selectOneByCode("OPC_URL");
// // 连接地址端口号
String endPointUrl = dictCode.getCodeValue();
// String endPointUrl = "opc.tcp://172.16.0.69:49320";
//安全策略选择
EndpointDescription[] endpointDescription = UaTcpStackClient.getEndpoints(endPointUrl).get();
//过滤掉不需要的安全策略,选择一个自己需要的安全策略
EndpointDescription endpoint = Arrays.stream(endpointDescription)
.filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getSecurityPolicyUri()))
.findFirst().orElseThrow(() -> new Exception("no desired endpoints returned"));
// 设置配置信息
OpcUaClientConfig config = OpcUaClientConfig.builder()
.setApplicationName(LocalizedText.english("pump")) // opc ua 自定义的名称
.setApplicationUri(endPointUrl)// 地址
.setEndpoint(endpoint)// 安全策略等配置
.setRequestTimeout(UInteger.valueOf(50000)) //等待时间
.build();
if (opcClient == null) {
opcClient = new OpcUaClient(config);// 准备连接
}
//开启连接
opcClient.connect().get();
Thread.sleep(2000);
return opcClient;
}
/**
* 获取节点信息
*
* @param client
* @throws Exception
*/
public static void browseNode(OpcUaClient client, NodeId nodeId) throws Exception {
//开启连接
client.connect().get();
if(nodeId == null){
nodeId = Identifiers.RootFolder;
}
List<Node> nodes = client.getAddressSpace().browse(nodeId).get();
for (Node node : nodes) {
System.out.println("Node= " + node.getBrowseName().get().getName());
browseNode(client, node.getNodeId().get());
}
}
/**
* 读取值
*
* @param client
* @throws Exception
*/
public static void readValues(OpcUaClient client, NodeId nodeId) throws Exception {
//创建连接
client.connect().get();
// NodeId nodeId = new NodeId(3, "\"test_value\"");
DataValue value = client.readValue(0.0, TimestampsToReturn.Both, nodeId).get();
System.out.println((Integer) value.getValue().getValue());
}
public static ArrayList<Object> readValues(OpcUaClient client, List<NodeId> nodeIds) throws Exception {
//创建连接
client.connect().get();
// NodeId nodeId = new NodeId(3, "\"test_value\"");
ArrayList<Object> results = new ArrayList<>();
List<DataValue> values = client.readValues(1, TimestampsToReturn.Both, nodeIds).get();
for (int i = 0; i < values.size(); i++) {
DataValue dataValue = values.get(i);
if(dataValue.getValue().getValue() == null){
System.out.println(
"---- opc key: " + nodeIds.get(i).getIdentifier().toString() + " " +
"--- read value: null" );
results.add("null");
}else{
System.out.println(
"---- opc key: " + nodeIds.get(i).getIdentifier().toString() + " " +
"--- read value: " + dataValue.getValue().getValue().toString());
results.add(dataValue.getValue().getValue()
.toString().trim().replaceAll(",", ""));
}
}
return results;
}
public static ArrayList<Object> readWaterChlorineInfoValues(OpcUaClient client) throws Exception {
String opcKeys = "ns=2;s=OPC.JL.PRIVATE.ID\n" +
"ns=2;s=OPC.JL.PRIVATE.Now\n" +
"ns=2;s=IFIX.OPC.FIX.AI.AI021601.A_CV\n" +
"ns=2;s=OPC.JL.PRIVATE.Null\n" +
"ns=2;s=IFIX.OPC.FIX.AI.AI040201.A_CV\n" +
"ns=2;s=IFIX.OPC.FIX.AI.AI040202.A_CV\n" +
"ns=2;s=IFIX.OPC.FIX.AI.AI040207.A_CV\n" +
"ns=2;s=IFIX.OPC.FIX.AI.AI040301.A_CV\n" +
"ns=2;s=IFIX.OPC.FIX.AI.AI040302.A_CV\n" +
"ns=2;s=IFIX.OPC.FIX.AI.AI040307.A_CV\n" +
"ns=2;s=IFIX.OPC.FIX.AI.AI040405.A_CV\n" +
"ns=2;s=IFIX.OPC.FIX.AI.AI050304.A_CV\n" +
"ns=2;s=IFIX.OPC.FIX.AI.PLC2_VD228.A_CV\n" +
"ns=2;s=XS.PLC3.VD124\n" +
"ns=2;s=XS.PLC3.VD132\n" +
"ns=2;s=XS.PLC3.VD140\n" +
"ns=2;s=IFIX.OPC2.FIX.AI.AI020202.A_CV\n" +
"ns=2;s=IFIX.OPC2.FIX.AI.AI020203.A_CV\n" +
"ns=2;s=IFIX.OPC2.FIX.AI.AI020301.A_CV\n" +
"ns=2;s=IFIX.OPC2.FIX.AI.AI020401.A_CV\n" +
"ns=2;s=IFIX.OPC2.FIX.AI.AI020404.A_CV\n" +
"ns=2;s=XS.PLC3.VD136\n" +
"ns=2;s=XS.PLC3.VD128\n" +
"ns=2;s=XS.PLC3.VD156\n" +
"ns=2;s=XS.PLC3.VD144\n" +
"ns=2;s=XS.PLC3.I03\n" +
"ns=2;s=XS.PLC3.I05\n" +
"ns=2;s=XS.PLC3.I07\n" +
"ns=2;s=XS.PLC3.I11\n" +
"ns=2;s=XS.PLC3.I13\n" +
"ns=2;s=XS.PLC3.VD200\n" +
"ns=2;s=XS.PLC3.VD204\n" +
"ns=2;s=XS.PLC3.VD208\n" +
"ns=2;s=XS.PLC3.VD212\n" +
"ns=2;s=XS.PLC3.VD216"
;
String[] keys = opcKeys.split("\n");
List<NodeId> nodeIds = new ArrayList<>();
for(String k: keys){
nodeIds.add(NodeId.parse(k));
}
return OpcUtil.readValues(client, nodeIds);
}
public static ArrayList<Object> readPumpFreeComputeInfo(OpcUaClient client) throws Exception {
String opcKeys =
"ns=2;s=XS.PLC3.VD124\n" +
"ns=2;s=XS.PLC3.VD132\n" +
"ns=2;s=XS.PLC3.VD140\n" +
"ns=2;s=XS.PLC3.VD136\n" +
"ns=2;s=XS.PLC3.VD128\n" +
"ns=2;s=XS.PLC3.VD156\n" +
"ns=2;s=XS.PLC3.VD144";
String[] keys = opcKeys.split("\n");
List<NodeId> nodeIds = new ArrayList<>();
for(String k: keys){
nodeIds.add(NodeId.parse(k));
}
return OpcUtil.readValues(client, nodeIds);
}
public static int setPumpFre(OpcUaClient client, int pumpId, BigDecimal value) throws Exception {
int VD124 = 0;
int VD128 = 4;
int VD156 = 5;
int VD136 = 3;
int VD132 = 1;
int VD140 = 2;
int VD144 = 6;
int result = 0;
ArrayList<Object> info = OpcUtil.readPumpFreeComputeInfo(client);
BigDecimal multiply = value.divide(BigDecimal.valueOf(50),
5, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(1415)).multiply(new BigDecimal(info.get(VD156).toString()));
if(pumpId == 1 ){
BigDecimal target = new BigDecimal(info.get(VD128).toString());
if(target.compareTo(new BigDecimal(0)) == 0){
target = new BigDecimal("0.001");
}
BigDecimal vd124 = multiply.divide(target,
5, RoundingMode.HALF_UP);
NodeId nodeId = NodeId.parse("ns=2;s=XS.PLC3.VD124");
OpcUtil.writeValue(client, vd124, nodeId);
result += 1;
}
if(pumpId == 2 || pumpId == 3){
BigDecimal target = new BigDecimal(info.get(VD136).toString());
if(target.compareTo(new BigDecimal(0)) == 0){
target = new BigDecimal("0.001");
}
// Long vd132 = value / 50 * 1415 * VD156 / VD136;
BigDecimal vd132 = multiply.divide(target,
5, RoundingMode.HALF_UP);
NodeId nodeId = NodeId.parse("ns=2;s=XS.PLC3.VD132");
OpcUtil.writeValue(client, vd132, nodeId);
result += 1;
}
if(pumpId == 4 || pumpId == 5){
BigDecimal target = new BigDecimal(info.get(VD144).toString());
if(target.compareTo(new BigDecimal(0)) == 0){
target = new BigDecimal("0.001");
}
// Long vd140 = value / 50 * 1415 * VD156 / VD144;
BigDecimal vd140 = multiply.divide(target,
5, RoundingMode.HALF_UP);
NodeId nodeId = NodeId.parse("ns=2;s=XS.PLC3.VD140");
OpcUtil.writeValue(client, vd140, nodeId);
result += 1;
}
return result;
}
/**
* 写入值
*
* @param client
* @param value
* @throws Exception
*/
public static void writeValue(OpcUaClient client, BigDecimal value, NodeId nodeId) throws Exception {
//创建连接
client.connect().get();
//创建变量节点
// NodeId nodeId = new NodeId(3, "\"test_value\"");
//创建Variant对象和DataValue对象
Variant v = new Variant(value.floatValue());
DataValue dataValue = new DataValue(v, null, null);
StatusCode statusCode = client.writeValue(nodeId, dataValue).get();
System.out.println(statusCode.getValue() + "+" + nodeId.toString() + "+" + value.floatValue());
System.out.println(statusCode.isGood()); // 写入成功返回值
}
public static void main(String[] args) throws Exception {
OpcUaClient opcUaClient = OpcUtil.createOpcClient();
// OpcUtil.writeValue(opcUaClient, BigDecimal.valueOf(12.555), NodeId.parse("ns=2;s=XS.PLC3.VD124"));
OpcUtil.setPumpFre(opcUaClient, 1, new BigDecimal("2.255"));
}
}
在需要用的地方使用,info就是 opc数据
OpcUtil.createOpcClient();
ArrayList<Object> info = OpcUtil.readWaterChlorineInfoValues(OpcUtil.opcClient);