Skip to content

Commit

Permalink
WIP dynamic datatype codecs
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinherron committed Sep 7, 2022
1 parent 11c8d0f commit 3714fbe
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 48 deletions.
Expand Up @@ -41,7 +41,7 @@ public static void main(String[] args) throws Exception {
@Override
public void run(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception {
// DataTypeTree reads DataTypeDefinition attributes while traversing the type hierarchy
// and registers codecs with the client's dynamic DataTypeManager.
// and, by default, registers codecs with the client's dynamic DataTypeManager.
client.addSessionInitializer(new DataTypeTreeSessionInitializer());

client.connect().get();
Expand Down
Expand Up @@ -30,6 +30,9 @@
/**
* Builds a {@link DataTypeTree} and stores it on an {@link OpcUaSession} as an attribute under
* the key {@link DataTypeTreeSessionInitializer#SESSION_ATTRIBUTE_KEY}.
* <p>
* Optionally, and by default, the tree will be traversed and dynamic DataTypeCodecs registered
* with the client's dynamic DataTypeManager for each structured and enumerated type.
*/
public class DataTypeTreeSessionInitializer implements SessionFsm.SessionInitializer {

Expand All @@ -41,64 +44,91 @@ public class DataTypeTreeSessionInitializer implements SessionFsm.SessionInitial
*/
public static final String SESSION_ATTRIBUTE_KEY = "dataTypeTree";

private final boolean registerCodecs;

/**
* Create a {@link DataTypeTreeSessionInitializer} that registers dynamic codecs once the tree
* is built.
*/
public DataTypeTreeSessionInitializer() {
this(true);
}

/**
* Create a {@link DataTypeTreeSessionInitializer} that optionally registers dynamic codecs
* once the tree is built.
*
* @param registerCodecs {@code true} if the tree should be traversed and dynamic codecs
* registered for all structured and enumerated types.
*/
public DataTypeTreeSessionInitializer(boolean registerCodecs) {
this.registerCodecs = registerCodecs;
}

@Override
public CompletableFuture<Unit> initialize(UaStackClient stackClient, OpcUaSession session) {
return DataTypeTreeBuilder.buildAsync(stackClient, session)
.thenAccept(tree -> {
session.setAttribute(SESSION_ATTRIBUTE_KEY, tree);

Tree<DataType> structureNode = tree.getTreeNode(NodeIds.Structure);
if (structureNode != null) {
structureNode.traverse(dataType -> {
DataTypeDefinition definition = dataType.getDataTypeDefinition();
if (registerCodecs) {
registerCodecs(stackClient, tree);
}
})
.thenApply(v -> Unit.VALUE);
}

private static void registerCodecs(UaStackClient stackClient, DataTypeTree tree) {
Tree<DataType> structureNode = tree.getTreeNode(NodeIds.Structure);
if (structureNode != null) {
structureNode.traverse(dataType -> {
DataTypeDefinition definition = dataType.getDataTypeDefinition();

if (definition instanceof StructureDefinition) {
var codec = new DynamicStructCodec((StructureDefinition) definition);
if (dataType.getBinaryEncodingId() != null) {
stackClient.getDynamicDataTypeManager().registerCodec(
dataType.getBinaryEncodingId(),
codec.asBinaryCodec()
);
stackClient.getDynamicDataTypeManager().registerCodec(
OpcUaDefaultBinaryEncoding.ENCODING_NAME,
dataType.getNodeId(),
codec.asBinaryCodec()
);
}
if (dataType.getXmlEncodingId() != null) {
stackClient.getDynamicDataTypeManager().registerCodec(
dataType.getXmlEncodingId(),
codec.asXmlCodec()
);
stackClient.getDynamicDataTypeManager().registerCodec(
OpcUaDefaultXmlEncoding.ENCODING_NAME,
dataType.getNodeId(),
codec.asXmlCodec()
);
}
// TODO register JSON codec
}
});
} else {
LoggerFactory.getLogger(DataTypeTreeSessionInitializer.class)
.warn("Tree for NodeIds.Structure not found; is the server DataType hierarchy sane?");
if (definition instanceof StructureDefinition) {
var codec = new DynamicStructCodec((StructureDefinition) definition);
if (dataType.getBinaryEncodingId() != null) {
stackClient.getDynamicDataTypeManager().registerCodec(
dataType.getBinaryEncodingId(),
codec.asBinaryCodec()
);
stackClient.getDynamicDataTypeManager().registerCodec(
OpcUaDefaultBinaryEncoding.ENCODING_NAME,
dataType.getNodeId(),
codec.asBinaryCodec()
);
}
if (dataType.getXmlEncodingId() != null) {
stackClient.getDynamicDataTypeManager().registerCodec(
dataType.getXmlEncodingId(),
codec.asXmlCodec()
);
stackClient.getDynamicDataTypeManager().registerCodec(
OpcUaDefaultXmlEncoding.ENCODING_NAME,
dataType.getNodeId(),
codec.asXmlCodec()
);
}
// TODO register JSON codec
}
});
} else {
LoggerFactory.getLogger(DataTypeTreeSessionInitializer.class)
.warn("Tree for NodeIds.Structure not found; is the server DataType hierarchy sane?");
}

Tree<DataType> enumerationNode = tree.getTreeNode(NodeIds.Enumeration);
if (enumerationNode != null) {
enumerationNode.traverse(dataType -> {
DataTypeDefinition definition = dataType.getDataTypeDefinition();
Tree<DataType> enumerationNode = tree.getTreeNode(NodeIds.Enumeration);
if (enumerationNode != null) {
enumerationNode.traverse(dataType -> {
DataTypeDefinition definition = dataType.getDataTypeDefinition();

if (definition instanceof EnumDefinition) {
// TODO register DynamicEnumCodec
}
});
} else {
LoggerFactory.getLogger(DataTypeTreeSessionInitializer.class)
.warn("Tree for NodeIds.Enumeration not found; is the server DataType hierarchy sane?");
if (definition instanceof EnumDefinition) {
// TODO register DynamicEnumCodec
}
})
.thenApply(v -> Unit.VALUE);
});
} else {
LoggerFactory.getLogger(DataTypeTreeSessionInitializer.class)
.warn("Tree for NodeIds.Enumeration not found; is the server DataType hierarchy sane?");
}
}

}

0 comments on commit 3714fbe

Please sign in to comment.