Skip to content

Commit

Permalink
Implement Matrix as a container for multidimensional array values
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinherron committed Sep 16, 2022
1 parent 95bbbe1 commit bff83ff
Show file tree
Hide file tree
Showing 155 changed files with 2,851 additions and 391 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 the Eclipse Milo Authors
* Copyright (c) 2022 the Eclipse Milo Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -84,7 +84,7 @@ public void browseWithBrowseDirection() throws UaException {

List<? extends UaNode> nodes = addressSpace.browseNodes(objectsFolderNode, browseOptions);

assertEquals(8, nodes.size());
assertEquals(9, nodes.size());
assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(NodeIds.RootFolder)));
assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(NodeIds.Server)));
assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(NodeIds.Aliases)));
Expand Down
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2022 the Eclipse Milo Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/

package org.eclipse.milo.opcua.sdk.client;

import org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode;
import org.eclipse.milo.opcua.sdk.core.types.DynamicStruct;
import org.eclipse.milo.opcua.sdk.test.AbstractClientServerTest;
import org.eclipse.milo.opcua.sdk.test.MatrixTestType;
import org.eclipse.milo.opcua.stack.core.UaException;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

public class DynamicMatrixTestTypeTest extends AbstractClientServerTest {

@Test
public void read() throws UaException {
AddressSpace addressSpace = client.getAddressSpace();

UaVariableNode testNode = (UaVariableNode) addressSpace.getNode(
new NodeId(2, "MatrixTestTypeValue")
);

DataValue value = testNode.readValue();
assertNotNull(value);

ExtensionObject xo = (ExtensionObject) value.getValue().getValue();
assert xo != null;

DynamicStruct decoded = (DynamicStruct) xo.decode(client.getDynamicEncodingContext());
assertEquals(MatrixTestType.TYPE_ID, decoded.getTypeId().absolute(client.getNamespaceTable()).orElseThrow());
System.out.println(decoded);
}

}
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2022 the Eclipse Milo Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/

package org.eclipse.milo.opcua.sdk.client;

import org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode;
import org.eclipse.milo.opcua.sdk.test.AbstractClientServerTest;
import org.eclipse.milo.opcua.sdk.test.MatrixTestType;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertNotNull;

public class StaticMatrixTestTypeTest extends AbstractClientServerTest {

@Test
public void read() throws Exception {
// Register Codecs for each supported encoding with DataTypeManager
client.getStaticDataTypeManager().registerType(
MatrixTestType.TYPE_ID.toNodeIdOrThrow(client.getNamespaceTable()),
new MatrixTestType.Codec(),
MatrixTestType.BINARY_ENCODING_ID.toNodeIdOrThrow(client.getNamespaceTable()),
null,
MatrixTestType.JSON_ENCODING_ID.toNodeIdOrThrow(client.getNamespaceTable())
);

AddressSpace addressSpace = client.getAddressSpace();

UaVariableNode testNode = (UaVariableNode) addressSpace.getNode(
new NodeId(2, "MatrixTestTypeValue")
);

DataValue value = testNode.readValue();
assertNotNull(value);

ExtensionObject xo = (ExtensionObject) value.getValue().getValue();
assert xo != null;

MatrixTestType decoded = (MatrixTestType) xo.decode(client.getStaticEncodingContext());
System.out.println(decoded);
}

}
Expand Up @@ -168,7 +168,9 @@ public void testGetEncodingIds() {
assertNotNull(treeNode);

treeNode.traverse(dataType -> {
if (!Objects.equals(dataType.getBrowseName().getName(), "Structure")) {
String name = dataType.getBrowseName().getName();

if (!Objects.equals(name, "Structure") && !Objects.equals(name, "MatrixTestType")) {
assertNotNull(dataType.getBinaryEncodingId());
assertNotNull(dataType.getXmlEncodingId());
assertNotNull(dataType.getJsonEncodingId());
Expand Down
Expand Up @@ -12,6 +12,7 @@

import java.util.concurrent.ExecutionException;

import org.eclipse.milo.opcua.sdk.client.DataTypeCodecSessionInitializer;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.dtd.BinaryDataTypeDictionarySessionInitializer;
import org.eclipse.milo.opcua.sdk.core.dtd.generic.StructCodec;
Expand Down Expand Up @@ -39,6 +40,7 @@ public void startClientAndServer() throws Exception {
server.startup().get();

client = TestClient.create(server);
client.addSessionInitializer(new DataTypeCodecSessionInitializer());
client.addSessionInitializer(new BinaryDataTypeDictionarySessionInitializer(StructCodec::new));

client.connect().get();
Expand Down
@@ -0,0 +1,122 @@
/*
* Copyright (c) 2022 the Eclipse Milo Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/

package org.eclipse.milo.opcua.sdk.test;

import java.util.Arrays;

import org.eclipse.milo.opcua.stack.core.BuiltinDataType;
import org.eclipse.milo.opcua.stack.core.UaSerializationException;
import org.eclipse.milo.opcua.stack.core.encoding.EncodingContext;
import org.eclipse.milo.opcua.stack.core.encoding.GenericDataTypeCodec;
import org.eclipse.milo.opcua.stack.core.encoding.UaDecoder;
import org.eclipse.milo.opcua.stack.core.encoding.UaEncoder;
import org.eclipse.milo.opcua.stack.core.types.UaStructuredType;
import org.eclipse.milo.opcua.stack.core.types.builtin.ExpandedNodeId;
import org.eclipse.milo.opcua.stack.core.types.builtin.Matrix;
import org.eclipse.milo.opcua.stack.core.types.enumerated.ApplicationType;
import org.eclipse.milo.opcua.stack.core.types.structured.XVType;

public class MatrixTestType implements UaStructuredType {

public static final ExpandedNodeId TYPE_ID = ExpandedNodeId.parse("nsu=urn:eclipse:milo:test;s=MatrixTestType.TypeId");
public static final ExpandedNodeId BINARY_ENCODING_ID = ExpandedNodeId.parse("nsu=urn:eclipse:milo:test;s=MatrixTestType.BinaryEncoding");
public static final ExpandedNodeId JSON_ENCODING_ID = ExpandedNodeId.parse("nsu=urn:eclipse:milo:test;s=MatrixTestType.JsonEncoding");

private final Integer[][] builtinMatrix;
private final ApplicationType[][] enumMatrix;
private final XVType[][] structMatrix;

public MatrixTestType(Integer[][] builtinMatrix, ApplicationType[][] enumMatrix, XVType[][] structMatrix) {
this.builtinMatrix = builtinMatrix;
this.enumMatrix = enumMatrix;
this.structMatrix = structMatrix;
}

public Integer[][] getBuiltinMatrix() {
return builtinMatrix;
}

public ApplicationType[][] getEnumMatrix() {
return enumMatrix;
}

public XVType[][] getStructMatrix() {
return structMatrix;
}

@Override
public ExpandedNodeId getTypeId() {
return TYPE_ID;
}

@Override
public ExpandedNodeId getBinaryEncodingId() {
return BINARY_ENCODING_ID;
}

@Override
public ExpandedNodeId getJsonEncodingId() {
return JSON_ENCODING_ID;
}

@Override
public String toString() {
return "MatrixTestType{" +
"builtinMatrix=" + Arrays.deepToString(builtinMatrix) +
", enumMatrix=" + Arrays.deepToString(enumMatrix) +
", structMatrix=" + Arrays.deepToString(structMatrix) +
'}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MatrixTestType that = (MatrixTestType) o;
return Arrays.deepEquals(builtinMatrix, that.builtinMatrix) &&
Arrays.deepEquals(enumMatrix, that.enumMatrix) &&
Arrays.deepEquals(structMatrix, that.structMatrix);
}

@Override
public int hashCode() {
int result = Arrays.hashCode(builtinMatrix);
result = 31 * result + Arrays.hashCode(enumMatrix);
result = 31 * result + Arrays.hashCode(structMatrix);
return result;
}

public static class Codec extends GenericDataTypeCodec<MatrixTestType> {

@Override
public Class<MatrixTestType> getType() {
return MatrixTestType.class;
}

@Override
public MatrixTestType decodeType(EncodingContext context, UaDecoder decoder) throws UaSerializationException {
Integer[][] builtinMatrix = (Integer[][]) decoder.decodeMatrix("BuiltinMatrix", BuiltinDataType.Int32).nestedArrayValue();
ApplicationType[][] enumMatrix = (ApplicationType[][]) decoder.decodeEnumMatrix("EnumMatrix").transform(e -> ApplicationType.from((Integer) e)).nestedArrayValue();
XVType[][] structMatrix = (XVType[][]) decoder.decodeStructMatrix("StructMatrix", XVType.TYPE_ID).nestedArrayValue();

return new MatrixTestType(builtinMatrix, enumMatrix, structMatrix);
}

@Override
public void encodeType(EncodingContext context, UaEncoder encoder, MatrixTestType value) throws UaSerializationException {
encoder.encodeMatrix("BuiltinMatrix", new Matrix(value.builtinMatrix));
encoder.encodeEnumMatrix("EnumMatrix", new Matrix(value.enumMatrix));
encoder.encodeStructMatrix("StructMatrix", new Matrix(value.structMatrix), XVType.TYPE_ID);
}

}

}

0 comments on commit bff83ff

Please sign in to comment.