springboot整合milo库实现对opc ua连接配置的动态修改
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.UaClient;
import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
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.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
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.springblade.coalface.listener.OpcSubscriptionListener;
import org.springblade.coalface.modules.communicate.entity.OpcUaCommunicate;
import org.springblade.coalface.modules.communicate.service.CommunicateService;
import org.springblade.coalface.modules.opcua.dto.OpcKey;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
@Slf4j
@Service
public class OpcUaTemplate {
@Resource
private CommunicateService communicateService;
private OpcUaClient opcUaClient;
@PostConstruct
private void init() {
try {
OpcUaCommunicate opcUaCommunicate= communicateService.getOpcUaCommunicate();
System.out.println(opcUaCommunicate);
if(opcUaCommunicate.getEnabled()){
opcUaClient=createClient(opcUaCommunicate.getEndPointUrl(),opcUaCommunicate.getUsername(),opcUaCommunicate.getPassword());
this.connect();
opcUaClient.getSubscriptionManager().createSubscription(1000.0).get();
opcUaClient.getSubscriptionManager().addSubscriptionListener(new OpcSubscriptionListener(opcUaClient));
}
} catch (UaException e) {
log.error(e.getMessage());
throw new RuntimeException(e);
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}
public OpcUaClient createClient(String endPointUrl,String username,String password) throws UaException {
Function<List<EndpointDescription>, Optional<EndpointDescription>> selectEndpoint = endpoints -> {
final Optional<EndpointDescription> endpoint = endpoints
.stream()
.filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
.findFirst();
EndpointDescription newEndpoint = new EndpointDescription(endPointUrl, endpoint.get().getServer(), endpoint.get().getServerCertificate(),
endpoint.get().getSecurityMode(), endpoint.get().getSecurityPolicyUri(), endpoint.get().getUserIdentityTokens(),
endpoint.get().getTransportProfileUri(), endpoint.get().getSecurityLevel());
return Optional.of(newEndpoint);
};
IdentityProvider identityProvider=new AnonymousProvider();
if(StringUtil.isNotBlank(username)&&StringUtil.isNotBlank(password)){
identityProvider=new UsernameProvider(username,password);
}
return OpcUaClient.create(endPointUrl,
selectEndpoint,
configBuilder -> configBuilder
.setApplicationName(LocalizedText.english("eclipse milo coalface client"))
.setApplicationUri("urn:eclipse:milo:coalface:client")
//访问方式
.setIdentityProvider(identityProvider)
.setRequestTimeout(UInteger.valueOf(60000))
.build()
);
}
public void connect() {
try {
opcUaClient.connect().whenComplete((result, ex) -> {
if (ex != null) {
log.error(ex.getMessage());
} else {
log.info("{} 连接成功!", opcUaClient.getConfig().getApplicationUri());
}
}).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
public void disconnect() {
if(Objects.nonNull(opcUaClient)) {
try {
opcUaClient.disconnect().whenComplete((result, ex) -> {
if (ex != null) {
log.error(ex.getMessage());
} else {
log.info("{} 断开连接成功!", opcUaClient.getConfig().getApplicationUri());
}
}).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}
public List<String> getBrowseKeys(String identifier) {
List<String> keys = new ArrayList<>(1000);
try {
opcUaClient.connect().get();
browse(identifier, keys, opcUaClient);
opcUaClient.disconnect().get();
} catch (Exception e) {
log.error(e.getMessage());
}
keys.remove(null);
return keys;
}
private void browse(String identifier, List<String> keys, UaClient client) throws Exception {
NodeId nodeId = Identifiers.ObjectsFolder;
if (!StringUtils.isEmpty(identifier)) {
nodeId = new NodeId(2, identifier);
}
BrowseDescription browse = new BrowseDescription(
nodeId,
BrowseDirection.Forward,
Identifiers.References,
true,
UInteger.valueOf(NodeClass.Object.getValue() | NodeClass.Variable.getValue()),
UInteger.valueOf(BrowseResultMask.All.getValue())
);
BrowseResult browseResult = client.browse(browse).get();
ReferenceDescription[] references = browseResult.getReferences();
for (ReferenceDescription reference : references) {
if (reference.getNodeClass().getValue() == NodeClass.Variable.getValue()) {
keys.add(reference.getNodeId().getIdentifier().toString());
}
browse(reference.getNodeId().getIdentifier().toString(), keys, client);
}
}
public List<DataValue> readValues(List<OpcKey> keys) {
// List<String> keyNames = getKeyNames(keys);
/* List<DataValue> res= BatchUtil.protectBach(keyNames, idList->{
return this.readValues(idList, client);
},1000);*/
List<DataValue> dataValues = new ArrayList<>(1000);
if (Objects.isNull(opcUaClient)) {
return dataValues;
}
if (CollectionUtil.isNotEmpty(keys)) {
List<NodeId> nodeIds = new ArrayList<>(1000);
keys.forEach(e -> {
NodeId nodeId = new NodeId(2, e.getPointAddress());
nodeIds.add(nodeId);
});
try {
dataValues = opcUaClient.readValues(0.0, TimestampsToReturn.Neither, nodeIds).get();
} catch (InterruptedException | ExecutionException e) {
log.error("{} {}", opcUaClient.getConfig().getApplicationUri(), e.getMessage());
}
}
return dataValues;
}
public void updateConfig(OpcUaCommunicate opcUaCommunicate) {
this.disconnect();
if(opcUaCommunicate.getEnabled()){
try {
opcUaClient=createClient(opcUaCommunicate.getEndPointUrl());
this.connect();
opcUaClient.getSubscriptionManager().createSubscription(1000.0).get();
opcUaClient.getSubscriptionManager().addSubscriptionListener(new OpcSubscriptionListener(opcUaClient));
} catch (UaException | ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}else{
opcUaClient=null;
}
}
}