You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ze...@apache.org on 2022/08/08 14:07:43 UTC
[incubator-streampipes] branch dev updated: [hotfix] Change behavior of OPC subscription mode
This is an automated email from the ASF dual-hosted git repository.
zehnder pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
The following commit(s) were added to refs/heads/dev by this push:
new e65c67350 [hotfix] Change behavior of OPC subscription mode
e65c67350 is described below
commit e65c673502c23fbcebb486d9844e7dfd131407e0
Author: Philipp Zehnder <ze...@fzi.de>
AuthorDate: Mon Aug 8 16:06:59 2022 +0200
[hotfix] Change behavior of OPC subscription mode
---
.../connect/iiot/adapters/opcua/OpcUaAdapter.java | 367 +++++++++++----------
.../iiot/adapters/opcua/utils/OpcUaUtil.java | 41 ++-
ui/cypress/tests/adapter/opcAdapter.ts | 2 +-
3 files changed, 222 insertions(+), 188 deletions(-)
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java
index 0538a0c7d..57039d1ee 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java
@@ -46,206 +46,231 @@ import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class OpcUaAdapter extends PullAdapter implements SupportsRuntimeConfig {
- public static final String ID = "org.apache.streampipes.connect.iiot.adapters.opcua";
- private static final Logger LOG = LoggerFactory.getLogger(OpcUaAdapter.class);
-
- private int pullingIntervalMilliSeconds;
- private SpOpcUaClient spOpcUaClient;
- private List<OpcNode> allNodes;
- private List<NodeId> allNodeIds;
- private int numberProperties;
- private Map<String, Object> event;
+ public static final String ID = "org.apache.streampipes.connect.iiot.adapters.opcua";
+ private static final Logger LOG = LoggerFactory.getLogger(OpcUaAdapter.class);
+
+ private int pullingIntervalMilliSeconds;
+ private SpOpcUaClient spOpcUaClient;
+ private List<OpcNode> allNodes;
+ private List<NodeId> allNodeIds;
+ private int numberProperties;
+ private final Map<String, Object> event;
+
+ /**
+ * This variable is used to map the node ids during the subscription to the labels of the nodes
+ */
+ private final Map<String, String> nodeIdToLabelMapping;
+
+ public OpcUaAdapter() {
+ super();
+ this.numberProperties = 0;
+ this.event = new HashMap<>();
+ this.nodeIdToLabelMapping = new HashMap<>();
+ }
- public OpcUaAdapter() {
- super();
- this.numberProperties = 0;
- this.event = new HashMap<>();
- }
+ public OpcUaAdapter(SpecificAdapterStreamDescription adapterStreamDescription) {
+ super(adapterStreamDescription);
+ this.numberProperties = 0;
+ this.event = new HashMap<>();
+ this.nodeIdToLabelMapping = new HashMap<>();
+ }
- public OpcUaAdapter(SpecificAdapterStreamDescription adapterStreamDescription) {
- super(adapterStreamDescription);
- this.numberProperties = 0;
- this.event = new HashMap<>();
- }
+ @Override
+ protected void before() throws AdapterException {
- @Override
- protected void before() throws AdapterException {
+ this.allNodeIds = new ArrayList<>();
+ try {
+ this.spOpcUaClient.connect();
+ OpcUaNodeBrowser browserClient =
+ new OpcUaNodeBrowser(this.spOpcUaClient.getClient(), this.spOpcUaClient.getSpOpcConfig());
+ this.allNodes = browserClient.findNodes();
- this.allNodeIds = new ArrayList<>();
- try {
- this.spOpcUaClient.connect();
- OpcUaNodeBrowser browserClient = new OpcUaNodeBrowser(this.spOpcUaClient.getClient(), this.spOpcUaClient.getSpOpcConfig());
- this.allNodes = browserClient.findNodes();
+ for (OpcNode node : this.allNodes) {
+ this.allNodeIds.add(node.nodeId);
+ }
- for (OpcNode node : this.allNodes) {
- this.allNodeIds.add(node.nodeId);
- }
+ if (spOpcUaClient.inPullMode()) {
+ this.pullingIntervalMilliSeconds = spOpcUaClient.getPullIntervalMilliSeconds();
+ } else {
+ this.numberProperties = this.allNodeIds.size();
+ this.spOpcUaClient.createListSubscription(this.allNodeIds, this);
+ }
- if (spOpcUaClient.inPullMode()) {
- this.pullingIntervalMilliSeconds = spOpcUaClient.getPullIntervalMilliSeconds();
- } else {
- this.numberProperties = this.allNodeIds.size();
- this.spOpcUaClient.createListSubscription(this.allNodeIds, this);
- }
+ this.allNodes.forEach(node -> this.nodeIdToLabelMapping.put(node.getNodeId().toString(), node.getLabel()));
- } catch (Exception e) {
- throw new AdapterException("The Connection to the OPC UA server could not be established.", e.getCause());
+ } catch (Exception e) {
+ throw new AdapterException("The Connection to the OPC UA server could not be established.", e.getCause());
+ }
}
- }
- @Override
- public void startAdapter() throws AdapterException {
+ @Override
+ public void startAdapter() throws AdapterException {
- this.spOpcUaClient = new SpOpcUaClient(SpOpcUaConfigBuilder.from(this.adapterDescription));
+ this.spOpcUaClient = new SpOpcUaClient(SpOpcUaConfigBuilder.from(this.adapterDescription));
- if (this.spOpcUaClient.inPullMode()) {
- super.startAdapter();
- } else {
- this.before();
+ if (this.spOpcUaClient.inPullMode()) {
+ super.startAdapter();
+ } else {
+ this.before();
+ }
}
- }
- @Override
- public void stopAdapter() throws AdapterException {
- // close connection
- this.spOpcUaClient.disconnect();
+ @Override
+ public void stopAdapter() throws AdapterException {
+ // close connection
+ this.spOpcUaClient.disconnect();
+
+ if (this.spOpcUaClient.inPullMode()) {
+ super.stopAdapter();
+ }
+ }
- if (this.spOpcUaClient.inPullMode()) {
- super.stopAdapter();
+ @Override
+ protected void pullData() {
+ CompletableFuture<List<DataValue>> response =
+ this.spOpcUaClient.getClient().readValues(0, TimestampsToReturn.Both, this.allNodeIds);
+ boolean badStatusCodeReceived = false;
+ boolean emptyValueReceived = false;
+ try {
+ List<DataValue> returnValues = response.get();
+ if (returnValues.size() == 0) {
+ emptyValueReceived = true;
+ LOG.warn("Empty value object returned - event will not be sent");
+ } else {
+ for (int i = 0; i < returnValues.size(); i++) {
+ var status = returnValues.get(i).getStatusCode();
+ if (StatusCode.GOOD.equals(status)) {
+ Object value = returnValues.get(i).getValue().getValue();
+ this.event.put(this.allNodes.get(i).getLabel(), value);
+ } else {
+ badStatusCodeReceived = true;
+ LOG.warn("Received status code {} for node label: {} - event will not be sent",
+ status,
+ this.allNodes.get(i).getLabel());
+ }
+ }
+ }
+ if (!badStatusCodeReceived && !emptyValueReceived) {
+ adapterPipeline.process(this.event);
+ }
+ } catch (InterruptedException | ExecutionException ie) {
+ LOG.error("Exception while reading data", ie);
+ }
}
- }
-
- @Override
- protected void pullData() {
- CompletableFuture<List<DataValue>> response = this.spOpcUaClient.getClient().readValues(0, TimestampsToReturn.Both, this.allNodeIds);
- boolean badStatusCodeReceived = false;
- boolean emptyValueReceived = false;
- try {
- List<DataValue> returnValues = response.get();
- if (returnValues.size() == 0) {
- emptyValueReceived = true;
- LOG.warn("Empty value object returned - event will not be sent");
- } else {
- for (int i = 0; i < returnValues.size(); i++) {
- var status = returnValues.get(i).getStatusCode();
- if (StatusCode.GOOD.equals(status)) {
- Object value = returnValues.get(i).getValue().getValue();
- this.event.put(this.allNodes.get(i).getLabel(), value);
- } else {
- badStatusCodeReceived = true;
- LOG.warn("Received status code {} for node label: {} - event will not be sent",
- status,
- this.allNodes.get(i).getLabel());
- }
+
+ public void onSubscriptionValue(UaMonitoredItem item, DataValue value) {
+
+ String key = this.nodeIdToLabelMapping.get(item.getReadValueId().getNodeId().toString());
+
+ OpcNode currNode = this.allNodes.stream()
+ .filter(node -> key.equals(node.getLabel()))
+ .findFirst()
+ .orElse(null);
+
+ if (currNode != null) {
+ event.put(currNode.getLabel(), value.getValue().getValue());
+
+ // ensure that event is complete and all opc ua subscriptions transmitted at least one value
+ if (event.keySet().size() >= this.numberProperties) {
+ Map<String, Object> newEvent = new HashMap<>();
+ // deep copy of event to prevent preprocessor error
+ for (String k : event.keySet()) {
+ newEvent.put(k, event.get(k));
+ }
+ adapterPipeline.process(newEvent);
+ }
+ } else {
+ LOG.error("No event is produced, because subscription item {} could not be found within all nodes", item);
}
- }
- if (!badStatusCodeReceived && !emptyValueReceived) {
- adapterPipeline.process(this.event);
- }
- } catch (InterruptedException | ExecutionException ie) {
- LOG.error("Exception while reading data", ie);
}
- }
- public void onSubscriptionValue(UaMonitoredItem item, DataValue value) {
+ @Override
+ protected PollingSettings getPollingInterval() {
+ return PollingSettings.from(TimeUnit.MILLISECONDS, this.pullingIntervalMilliSeconds);
+ }
+
+ @Override
+ public SpecificAdapterStreamDescription declareModel() {
+
+ SpecificAdapterStreamDescription description = SpecificDataStreamAdapterBuilder
+ .create(ID)
+ .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+ .withLocales(Locales.EN)
+ .category(AdapterType.Generic, AdapterType.Manufacturing)
+ .requiredAlternatives(Labels.withId(OpcUaLabels.ADAPTER_TYPE.name()),
+ Alternatives.from(Labels.withId(OpcUaLabels.PULL_MODE.name()),
+ StaticProperties.integerFreeTextProperty(
+ Labels.withId(OpcUaLabels.PULLING_INTERVAL.name()))),
+ Alternatives.from(Labels.withId(OpcUaLabels.SUBSCRIPTION_MODE.name())))
+ .requiredAlternatives(Labels.withId(OpcUaLabels.ACCESS_MODE.name()),
+ Alternatives.from(Labels.withId(OpcUaLabels.UNAUTHENTICATED.name())),
+ Alternatives.from(Labels.withId(OpcUaLabels.USERNAME_GROUP.name()),
+ StaticProperties.group(
+ Labels.withId(OpcUaLabels.USERNAME_GROUP.name()),
+ StaticProperties.stringFreeTextProperty(
+ Labels.withId(OpcUaLabels.USERNAME.name())),
+ StaticProperties.secretValue(Labels.withId(OpcUaLabels.PASSWORD.name()))
+ ))
+ )
+ .requiredAlternatives(Labels.withId(OpcUaLabels.OPC_HOST_OR_URL.name()),
+ Alternatives.from(
+ Labels.withId(OpcUaLabels.OPC_URL.name()),
+ StaticProperties.stringFreeTextProperty(
+ Labels.withId(OpcUaLabels.OPC_SERVER_URL.name()), "opc.tcp://localhost:4840"))
+ ,
+ Alternatives.from(Labels.withId(OpcUaLabels.OPC_HOST.name()),
+ StaticProperties.group(
+ Labels.withId("host-port"),
+ StaticProperties.stringFreeTextProperty(
+ Labels.withId(OpcUaLabels.OPC_SERVER_HOST.name())),
+ StaticProperties.stringFreeTextProperty(
+ Labels.withId(OpcUaLabels.OPC_SERVER_PORT.name()))
+ ))
+ )
+ .requiredTextParameter(Labels.withId(OpcUaLabels.NAMESPACE_INDEX.name()))
+ .requiredTextParameter(Labels.withId(OpcUaLabels.NODE_ID.name()))
+ .requiredRuntimeResolvableTreeInput(
+ Labels.withId(OpcUaLabels.AVAILABLE_NODES.name()),
+ Arrays.asList(OpcUaLabels.NAMESPACE_INDEX.name(), OpcUaLabels.NODE_ID.name())
+ )
+ .build();
+
+ description.setAppId(ID);
+
+ return description;
+ }
- String key = OpcUaUtil.getRuntimeNameOfNode(item.getReadValueId().getNodeId());
+ @Override
+ public Adapter getInstance(SpecificAdapterStreamDescription adapterDescription) {
+ return new OpcUaAdapter(adapterDescription);
+ }
- OpcNode currNode = this.allNodes.stream()
- .filter(node -> key.equals(node.getNodeId().getIdentifier().toString()))
- .findFirst()
- .orElse(null);
+ @Override
+ public GuessSchema getSchema(SpecificAdapterStreamDescription adapterDescription)
+ throws AdapterException, ParseException {
+ return OpcUaUtil.getSchema(adapterDescription);
+ }
- event.put(currNode.getLabel(), value.getValue().getValue());
+ @Override
+ public String getId() {
+ return ID;
+ }
- // ensure that event is complete and all opc ua subscriptions transmitted at least one value
- if (event.keySet().size() >= this.numberProperties) {
- Map<String, Object> newEvent = new HashMap<>();
- // deep copy of event to prevent preprocessor error
- for (String k : event.keySet()) {
- newEvent.put(k, event.get(k));
- }
- adapterPipeline.process(newEvent);
+ @Override
+ public StaticProperty resolveConfiguration(String staticPropertyInternalName, StaticPropertyExtractor extractor) {
+ return OpcUaUtil.resolveConfiguration(staticPropertyInternalName, extractor);
}
- }
-
- @Override
- protected PollingSettings getPollingInterval() {
- return PollingSettings.from(TimeUnit.MILLISECONDS, this.pullingIntervalMilliSeconds);
- }
-
- @Override
- public SpecificAdapterStreamDescription declareModel() {
-
- SpecificAdapterStreamDescription description = SpecificDataStreamAdapterBuilder
- .create(ID)
- .withAssets(Assets.DOCUMENTATION, Assets.ICON)
- .withLocales(Locales.EN)
- .category(AdapterType.Generic, AdapterType.Manufacturing)
- .requiredAlternatives(Labels.withId(OpcUaLabels.ADAPTER_TYPE.name()),
- Alternatives.from(Labels.withId(OpcUaLabels.PULL_MODE.name()),
- StaticProperties.integerFreeTextProperty(Labels.withId(OpcUaLabels.PULLING_INTERVAL.name()))),
- Alternatives.from(Labels.withId(OpcUaLabels.SUBSCRIPTION_MODE.name())))
- .requiredAlternatives(Labels.withId(OpcUaLabels.ACCESS_MODE.name()),
- Alternatives.from(Labels.withId(OpcUaLabels.UNAUTHENTICATED.name())),
- Alternatives.from(Labels.withId(OpcUaLabels.USERNAME_GROUP.name()),
- StaticProperties.group(
- Labels.withId(OpcUaLabels.USERNAME_GROUP.name()),
- StaticProperties.stringFreeTextProperty(Labels.withId(OpcUaLabels.USERNAME.name())),
- StaticProperties.secretValue(Labels.withId(OpcUaLabels.PASSWORD.name()))
- ))
- )
- .requiredAlternatives(Labels.withId(OpcUaLabels.OPC_HOST_OR_URL.name()),
- Alternatives.from(
- Labels.withId(OpcUaLabels.OPC_URL.name()),
- StaticProperties.stringFreeTextProperty(Labels.withId(OpcUaLabels.OPC_SERVER_URL.name()), "opc.tcp://localhost:4840"))
- ,
- Alternatives.from(Labels.withId(OpcUaLabels.OPC_HOST.name()),
- StaticProperties.group(
- Labels.withId("host-port"),
- StaticProperties.stringFreeTextProperty(Labels.withId(OpcUaLabels.OPC_SERVER_HOST.name())),
- StaticProperties.stringFreeTextProperty(Labels.withId(OpcUaLabels.OPC_SERVER_PORT.name()))
- ))
- )
- .requiredTextParameter(Labels.withId(OpcUaLabels.NAMESPACE_INDEX.name()))
- .requiredTextParameter(Labels.withId(OpcUaLabels.NODE_ID.name()))
- .requiredRuntimeResolvableTreeInput(
- Labels.withId(OpcUaLabels.AVAILABLE_NODES.name()),
- Arrays.asList(OpcUaLabels.NAMESPACE_INDEX.name(), OpcUaLabels.NODE_ID.name())
- )
- .build();
-
- description.setAppId(ID);
-
- return description;
- }
-
- @Override
- public Adapter getInstance(SpecificAdapterStreamDescription adapterDescription) {
- return new OpcUaAdapter(adapterDescription);
- }
-
- @Override
- public GuessSchema getSchema(SpecificAdapterStreamDescription adapterDescription) throws AdapterException, ParseException {
- return OpcUaUtil.getSchema(adapterDescription);
- }
-
- @Override
- public String getId() {
- return ID;
- }
-
- @Override
- public StaticProperty resolveConfiguration(String staticPropertyInternalName, StaticPropertyExtractor extractor) {
- return OpcUaUtil.resolveConfiguration(staticPropertyInternalName, extractor);
- }
}
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java
index 9e5ed16bf..3bf5430c8 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java
@@ -66,7 +66,8 @@ public class OpcUaUtil {
* @throws AdapterException
* @throws ParseException
*/
- public static GuessSchema getSchema(SpecificAdapterStreamDescription adapterStreamDescription) throws AdapterException, ParseException {
+ public static GuessSchema getSchema(SpecificAdapterStreamDescription adapterStreamDescription)
+ throws AdapterException, ParseException {
GuessSchema guessSchema = new GuessSchema();
EventSchema eventSchema = new EventSchema();
List<EventProperty> allProperties = new ArrayList<>();
@@ -75,22 +76,23 @@ public class OpcUaUtil {
try {
spOpcUaClient.connect();
- OpcUaNodeBrowser nodeBrowser = new OpcUaNodeBrowser(spOpcUaClient.getClient(), spOpcUaClient.getSpOpcConfig());
+ OpcUaNodeBrowser nodeBrowser =
+ new OpcUaNodeBrowser(spOpcUaClient.getClient(), spOpcUaClient.getSpOpcConfig());
List<OpcNode> selectedNodes = nodeBrowser.findNodes();
if (!selectedNodes.isEmpty()) {
for (OpcNode opcNode : selectedNodes) {
if (opcNode.hasUnitId()) {
allProperties.add(PrimitivePropertyBuilder
- .create(opcNode.getType(), opcNode.getLabel())
- .label(opcNode.getLabel())
- .measurementUnit(new URI(opcNode.getQudtURI()))
- .build());
+ .create(opcNode.getType(), opcNode.getLabel())
+ .label(opcNode.getLabel())
+ .measurementUnit(new URI(opcNode.getQudtURI()))
+ .build());
} else {
allProperties.add(PrimitivePropertyBuilder
- .create(opcNode.getType(), opcNode.getLabel())
- .label(opcNode.getLabel())
- .build());
+ .create(opcNode.getType(), opcNode.getLabel())
+ .label(opcNode.getLabel())
+ .build());
}
}
@@ -110,13 +112,16 @@ public class OpcUaUtil {
/***
- * OPC UA specific implementation of {@link org.apache.streampipes.container.api.ResolvesContainerProvidedOptions#resolveOptions(String, StaticPropertyExtractor)}. }
+ * OPC UA specific implementation of {@link
+ * org.apache.streampipes.container.api.ResolvesContainerProvidedOptions#
+ * resolveOptions(String, StaticPropertyExtractor)}.
* @param internalName The internal name of the Static Property
* @param parameterExtractor
* @return {@code List<Option>} with available node names for the given OPC UA configuration
*/
- public static RuntimeResolvableTreeInputStaticProperty resolveConfiguration (String internalName,
- StaticPropertyExtractor parameterExtractor) {
+ public static RuntimeResolvableTreeInputStaticProperty
+ resolveConfiguration(String internalName,
+ StaticPropertyExtractor parameterExtractor) {
RuntimeResolvableTreeInputStaticProperty config = parameterExtractor
.getStaticPropertyByName(internalName, RuntimeResolvableTreeInputStaticProperty.class);
@@ -129,9 +134,10 @@ public class OpcUaUtil {
}
SpOpcUaClient spOpcUaClient = new SpOpcUaClient(SpOpcUaConfigBuilder.from(parameterExtractor));
- try{
+ try {
spOpcUaClient.connect();
- OpcUaNodeBrowser nodeBrowser = new OpcUaNodeBrowser(spOpcUaClient.getClient(), spOpcUaClient.getSpOpcConfig());
+ OpcUaNodeBrowser nodeBrowser =
+ new OpcUaNodeBrowser(spOpcUaClient.getClient(), spOpcUaClient.getSpOpcConfig());
config.setNodes(nodeBrowser.buildNodeTreeFromOrigin());
spOpcUaClient.disconnect();
} catch (Exception e) {
@@ -156,17 +162,20 @@ public class OpcUaUtil {
/**
* connects to each node individually and updates the data type in accordance to the data from the server.
+ *
* @param opcNodes List of opcNodes where the data type is not determined appropriately
*/
public static void retrieveDataTypesFromServer(OpcUaClient client, List<OpcNode> opcNodes) throws AdapterException {
for (OpcNode opcNode : opcNodes) {
try {
- UInteger dataTypeId = (UInteger) client.getAddressSpace().getVariableNode(opcNode.getNodeId()).getDataType().getIdentifier();
+ UInteger dataTypeId =
+ (UInteger) client.getAddressSpace().getVariableNode(opcNode.getNodeId()).getDataType()
+ .getIdentifier();
OpcUaTypes.getType(dataTypeId);
opcNode.setType(OpcUaTypes.getType(dataTypeId));
} catch (UaException e) {
- throw new AdapterException("Could not guess schema for opc node! " + e.getMessage());
+ throw new AdapterException("Could not guess schema for opc node! " + e.getMessage());
}
}
}
diff --git a/ui/cypress/tests/adapter/opcAdapter.ts b/ui/cypress/tests/adapter/opcAdapter.ts
index 74ad8ba60..8ec8e54ec 100644
--- a/ui/cypress/tests/adapter/opcAdapter.ts
+++ b/ui/cypress/tests/adapter/opcAdapter.ts
@@ -47,7 +47,7 @@ describe('Test OPC-UA Adapter Subscription Mode', () => {
const getAdapterBuilder = (pullMode: boolean) => {
- const host: string = ParameterUtils.get('ipe-girlitz.fzi.de', 'opcua');
+ const host: string = ParameterUtils.get('localhost', 'opcua');
const builder = SpecificAdapterBuilder
.create('OPC_UA')