Skip to content
Snippets Groups Projects
Commit 09b031fe authored by Guillaume PICHON's avatar Guillaume PICHON
Browse files

Correction of the state after a connection. Adding a method to retrieve infos for a given node.

parent 03c452a1
No related branches found
No related tags found
No related merge requests found
......@@ -50,13 +50,13 @@
<dependency>
<groupId>org.eclipse.milo</groupId>
<artifactId>sdk-client</artifactId>
<version>0.6.7</version>
<version>0.6.11</version>
</dependency>
<dependency>
<groupId>org.eclipse.milo</groupId>
<artifactId>dictionary-reader</artifactId>
<version>0.6.7</version>
<version>0.6.11</version>
</dependency>
<dependency>
......
......@@ -20,6 +20,7 @@ import org.tango.utils.DevFailedUtils;
import fr.esrf.Tango.AttrDataFormat;
import fr.esrf.Tango.DevFailed;
import fr.esrf.TangoDs.TangoConst;
public abstract class OpcUaTangoUtils {
......@@ -55,7 +56,8 @@ public abstract class OpcUaTangoUtils {
}
public String toString() {
return format.toString() + " " + type.name();
return TangoConst.Tango_AttrDataFormatName[format.value()] + " "
+ TangoConst.Tango_CmdArgTypeName[type.getTangoIDLType()];
}
public Class<? extends Object> getTangoClass() {
......
......@@ -7,6 +7,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
......@@ -275,7 +276,17 @@ public class OpcUaConnector extends AOpcUaSubscriber {
long intervalBetweenConnectionAttemptsMs = (long) (intervalBetweenConnectionAttempts * 1000.0 + 0.5);
connectionLooper = new ConnectionLooper(connectionMaximumAttempts, intervalBetweenConnectionAttemptsMs);
connectionLooper.setFirstConnection();
connectionExecutor.submit(connectionLooper);
CompletableFuture<Void> future = CompletableFuture.runAsync(connectionLooper, connectionExecutor);
future.whenComplete((none, error) -> {
if (error != null) {
String errorMsg = "Initial connection finished on error: " + error.getMessage();
logger.error(errorMsg, error);
setStateStatus(DeviceState.FAULT, errorMsg, false);
} else {
setState(DeviceState.ON);
}
});
// connectionExecutor.submit(connectionLooper);
logger.debug("init done for device {} ", deviceManager.getName());
}
......@@ -353,11 +364,13 @@ public class OpcUaConnector extends AOpcUaSubscriber {
SubscriptionResult result = createOPCUAAttributesByBrowsing(sessionSimpleNodeId, false,
requestedPublishingIntervalForDiagnostic, samplingIntervalForSubscriptionForDiagnostic,
Collections.emptySet(), this);
if (result != null) {
int nbCreated = createTangoAttributes(result);
if (nbCreated > 0) {
this.diagnosticAttributes = result;
}
}
}
@Command(name = "RemoveDiagnosticAttributes", inTypeDesc = "Remove the diagnostic attributes.", outTypeDesc = "")
public void removeDiagnosticAttributes() throws DevFailed {
......@@ -430,6 +443,25 @@ public class OpcUaConnector extends AOpcUaSubscriber {
return result;
}
/**
*
* @param argin
* @return
* @throws DevFailed
*/
@Command(name = "ReadNodeInfo", inTypeDesc = "Read the infos of a given node", outTypeDesc = "Node type, node format, ...")
@StateMachine(deniedStates = { DeviceState.FAULT, DeviceState.RUNNING })
public String[] readNodeInfo(final String nodeToRead) throws DevFailed {
String identifierToRead = nodeToRead.trim();
OpcUaSimpleNode simpleNode = splitNamespaceTypeId(identifierToRead);
String[] result = { "Invalid node description." };
if (simpleNode != null) {
logger.info("Reading node infos {}", simpleNode.getNodeId().toParseableString());
result = opcUaProxyClient.readNodeInfo(simpleNode);
}
return result;
}
private void receivedAsyncReply(String[] reply) {
synchronized (asyncReplyResultAttribute) {
asyncReplyResultAttribute = reply;
......
......@@ -67,6 +67,7 @@ import fr.soleil.opcuaproxy.attributes.OpcUaSimpleNode;
import fr.soleil.opcuaproxy.attributes.OpcUaSubscribedAttribute;
import fr.soleil.opcuaproxy.attributes.OpcUaSubscribedAttributeParameters;
import fr.soleil.opcuaproxy.attributes.OpcUaTangoUtils;
import fr.soleil.opcuaproxy.attributes.OpcUaTangoUtils.FullTangoType;
import fr.soleil.opcuaproxy.attributes.build.OpcUaAttributeBuildParameters;
import fr.soleil.opcuaproxy.attributes.build.OpcUaAttributeFactory;
import fr.soleil.opcuaproxy.attributes.build.OpcUaPolledAttributeBuilderParameters;
......@@ -288,6 +289,133 @@ class OpcUaProxyClient implements IOpcUaNodeReaderWriter {
}
}
/**
* Read a node on the OPC-UA server. If the node is a structure, every value
* will be read.
*
* @param nodeToRead The node to read.
* @return An array of string representing the answer.
* @throws DevFailed Potentially a UaException encapsulated.
*/
public String[] readNodeInfo(final OpcUaSimpleNode nodeToRead) throws DevFailed {
List<String> resultList = new ArrayList<>();
try {
UaNode node = client.getAddressSpace().getNode(nodeToRead.getNodeId());
node.getBrowseName();
NodeClass nc = node.getNodeClass();
resultList.add(dumpUaNode(node));
switch (nc) {
case DataType:
break;
case Method:
UaMethodNode uaMethodNode = (UaMethodNode) node;
Boolean executable = uaMethodNode.readExecutable();
Boolean userExecutable = uaMethodNode.readUserExecutable();
resultList.add("Is executable = " + executable);
resultList.add("Is user executable = " + userExecutable);
try {
String nodeVersion = uaMethodNode.readNodeVersionAsync().get();
resultList.add("Node version = " + nodeVersion);
} catch (InterruptedException e) {
logger.error("Impossible to retreive method node version: " + e.getMessage(), e);
} catch (ExecutionException e) {
resultList.add("No node version");
}
try {
Argument[] inputArgs = uaMethodNode.readInputArgumentsAsync().get();
if (inputArgs.length > 0) {
for (int i = 0; i < inputArgs.length; i++) {
resultList.add(
"Input argument [" + i + "]=" + OpcUaMethod.getArgumentDescription(inputArgs[i]));
}
} else {
resultList.add("No input arguments");
}
} catch (InterruptedException | ExecutionException e) {
resultList.add("Impossible to retreive method input args details for analyse: " + e.getMessage());
logger.error("Impossible to retreive method input args details for analyse: " + e.getMessage(), e);
}
try {
Argument[] outputArgs = uaMethodNode.readOutputArgumentsAsync().get();
if (outputArgs.length > 0) {
for (int i = 0; i < outputArgs.length; i++) {
resultList.add(
"Output argument [" + i + "]=" + OpcUaMethod.getArgumentDescription(outputArgs[i]));
}
} else {
resultList.add("No output arguments");
}
} catch (InterruptedException | ExecutionException e) {
resultList.add("Impossible to retreive method output args details for analyse: " + e.getMessage());
logger.error("Impossible to retreive method output args details for analyse: " + e.getMessage(), e);
}
break;
case Object:
case ObjectType:
case ReferenceType:
case Unspecified:
// Nothing more to say...
break;
case Variable:
try {
DataValue value = getDataValue(nodeToRead);
boolean nullValue = true;
if (value != null) {
Variant variant = value.getValue();
if (variant != null) {
Object nodeValue = variant.getValue();
if (nodeValue != null) {
resultList.add("OpcUa type=" + nodeValue.getClass().getSimpleName());
FullTangoType tangoType = OpcUaTangoUtils.getTangoType(nodeValue);
if (tangoType != null) {
resultList.add("Tango type=" + tangoType.toString());
} else {
resultList.add("Tango type=Unknown");
}
nullValue = false;
}
}
}
if (nullValue) {
resultList.add("The value is currently null, no type analyse.");
}
UaVariableNode vnode = (UaVariableNode) node;
try {
@javax.annotation.Nullable
UInteger[] arrayDim = vnode.readArrayDimensions();
if (arrayDim != null && arrayDim.length > 0) {
StringBuilder strBldr = new StringBuilder("Dimension sizes=[");
for (int i = 0; i < arrayDim.length; i++) {
if (i != 0) {
strBldr.append(',');
}
strBldr.append(arrayDim[i].intValue());
}
resultList.add(strBldr.toString());
}
} catch (UaException uae) {
// No array dim.
}
} catch (UaException uae) {
resultList.add("Impossible to retreive value for analyse: " + uae.getMessage());
logger.error("Impossible to retreive value for analyse: " + uae.getMessage(), uae);
}
break;
case VariableType:
break;
case View:
break;
default:
break;
}
} catch (UaException e) {
throw DevFailedUtils.newDevFailed(e);
}
return resultList.toArray(new String[0]);
}
public Map<OpcUaAttributeReference, Set<OpcUaPolledAttribute>> buildPolledAttribute(
List<OpcUaPolledAttributeParameters> parametersList) throws DevFailed {
Map<OpcUaAttributeReference, Set<OpcUaPolledAttribute>> result = new TreeMap<>();
......@@ -524,6 +652,7 @@ class OpcUaProxyClient implements IOpcUaNodeReaderWriter {
for (OpcUaSimpleNode node : leafNodes) {
try {
UaNode uaNode = client.getAddressSpace().getNode(node.getNodeId());
if (uaNode.getNodeClass() == NodeClass.Variable) {
String name = node.getOpcuaIdStr();
String label = uaNode.getDisplayName().getLocale();
if (label == null) {
......@@ -542,8 +671,10 @@ class OpcUaProxyClient implements IOpcUaNodeReaderWriter {
}
// It's a leaf, it cannot be browsed.
OpcUaSubscribedAttributeParameters attributeParameters = new OpcUaSubscribedAttributeParameters(
name, label, activatedEvents, attrRef, writeAttrRef, samplingInterval, false, false);
name, label, activatedEvents, attrRef, writeAttrRef, samplingInterval, false,
false);
parametersList.add(attributeParameters);
}
} catch (UaException e) {
logger.error("Error while retreiving the node " + node.toString());
throw e;
......@@ -720,24 +851,11 @@ class OpcUaProxyClient implements IOpcUaNodeReaderWriter {
List<? extends UaNode> nodes = client.getAddressSpace().browseNodes(browseRoot);
for (UaNode node : nodes) {
NodeId nodeId = node.getNodeId();
NodeClass nodeClass = node.getNodeClass();
StringBuilder nodeStringBldr = new StringBuilder();
nodeStringBldr.append(indent);
nodeStringBldr.append("Node=");
nodeStringBldr.append(nodeId.toParseableString());
nodeStringBldr.append(" browseName=");
nodeStringBldr.append(node.getBrowseName().getName());
nodeStringBldr.append(" nodeClass=");
nodeStringBldr.append(nodeClass.name());
if (nodeClass == NodeClass.Variable) {
nodeStringBldr.append(" readableName=");
nodeStringBldr.append(AOpcUaSubscriber.toReadableName(nodeId));
}
nodeStringBldr.append(dumpUaNode(node));
result.add(indent + "ns=" + Integer.toString(nodeId.getNamespaceIndex().intValue()) + ", browseName="
+ node.getBrowseName().getName() + ", id=" + nodeId.getIdentifier().toString() + ", type="
+ nodeId.getType().toString() + ", nodeClass=" + nodeClass.name());
result.add(nodeStringBldr.toString());
// recursively browse to children
result.addAll(browseNode(indent + "\t", node.getNodeId()));
}
......@@ -750,6 +868,25 @@ class OpcUaProxyClient implements IOpcUaNodeReaderWriter {
return result;
}
private static String dumpUaNode(UaNode node) {
NodeId nodeId = node.getNodeId();
NodeClass nodeClass = node.getNodeClass();
StringBuilder nodeStringBldr = new StringBuilder();
nodeStringBldr.append("Node=");
nodeStringBldr.append(nodeId.toParseableString());
nodeStringBldr.append(" browseName=");
nodeStringBldr.append(node.getBrowseName().getName());
nodeStringBldr.append(" nodeClass=");
nodeStringBldr.append(nodeClass.name());
nodeStringBldr.append(" nodeDetailedClass=");
nodeStringBldr.append(node.getClass().getSimpleName());
if (nodeClass == NodeClass.Variable) {
nodeStringBldr.append(" readableName=");
nodeStringBldr.append(AOpcUaSubscriber.toReadableName(nodeId));
}
return nodeStringBldr.toString();
}
public boolean unsubscribeTo(UInteger subscriptioId) throws DevFailed {
UaSubscription deletedSubscription = null;
try {
......
......@@ -187,7 +187,7 @@ public class OpcUaMethod implements ICommandBehavior, Comparable<OpcUaMethod> {
}
}
private static String getArgumentDescription(Argument argument) {
public static String getArgumentDescription(Argument argument) {
String fullDesc = null;
String desc = null;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment