0

我正在尝试在 Eclipse Milo OpcUa 服务器上编写一个 ExtensionObject 数组。我在 Java 8 和 Milo 0.2.3 上做这一切。

我测试我写到我的服务器的方法是统一自动化 UaExpert 客户端和一个小的 Python 客户端。两者都显示相同的结果。

我有以下结构(我为此场景命名为 MyStructure)。它已经作为数组存在,我想将它写入相应的节点。

@Getter
@Setter
@AllArgsConstructor
public class MyStructure implements UaStructure {
    private String name;
    private Integer dataType;
    private String stringValue;
    private Integer intValue;
    private Float floatValue;

    public static final String Description = "MyStructure ";

    public static NodeId getNodeId() {
        return new NodeId(2, 3081);
    }

    @Override
    public NodeId getTypeId() {
        return getNodeId();
    }

    @Override
    public NodeId getBinaryEncodingId() {
        return getNodeId();
    }

    @Override
    public NodeId getXmlEncodingId() {
        return getNodeId();
    }

    public static class Codec extends GenericDataTypeCodec<MyStructure > {

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

        @Override
        public MyStructure decode(SerializationContext context, UaDecoder reader) {
            return new MyStructure (
                reader.readString("Name"),
                reader.readInt32("DataType"),
                reader.readString("StringValue"),
                reader.readInt32("IntValue"),
                reader.readFloat("FloatValue")
            );
        }

        @Override
        public void encode(SerializationContext context, MyStructure myStructure, UaEncoder writer) {
            writer.writeString("Name", myStructure.getName());
            writer.writeInt32("DataType", myStructure.getDataType());
            writer.writeString("StringValue", myStructure.getStringValue());
            writer.writeInt32("IntValue", myStructure.getIntValue());
            writer.writeFloat("FloatValue", myStructure.getFloatValue());
        }
    }
}

我这样编写节点,其中节点是 UaVariableNode 的一个实例,并将我的 Array 对象排列成数组,我创建的对象是这样的:

node.setValue(new DataValue(new Variant(array)));

Object array = Array.newInstance(MyStructure.class, myStructureList.size());
for (int i = 0; i < myStructureList.size(); i++) {
    Array.set(array, i,myStructureList.get(i));
}

我事先注册了 MyStructure 定义,如下所示:

OpcUaBinaryDataTypeDictionary dictionary = new OpcUaBinaryDataTypeDictionary("mynamespace");
dictionary.registerStructCodec(
        new MyStructure.Codec().asBinaryCodec(),
        "MyStructure",
        new NodeId(2, 3081)
    );
OpcUaDataTypeManager.getInstance().registerTypeDictionary(dictionary);

每当我设置节点时,服务器都不会抱怨。它实际上设置了一些东西,准确地说它设置了 42 个扩展对象。在 UaExpert 中,我看到值(包括其时间戳)发生了变化,但我看不到实际值。该值只是 ExtensionObject 数组类型,我无法读取任何嵌套值。但这就是我在其他项目中看到的。它们具有自定义结构,并且嵌套字段在 UaExpert 中是人类可读的。

如果我在没有数组的情况下只写一个 MyStructure,问题不会改变。

你有什么想法,我做错了什么或根本没有做什么?

4

1 回答 1

0

目前,Milo 中的自定义结构只有在读取/写入它们的客户提前知道该结构时才有效。

您所缺少的(并且尚未由 Milo 实现)是围绕创建 DataTypeDictionary、在地址空间中注册以及通过 DataTypeEncoding 将编解码器链接到该字典中的条目的所有复杂性。

如果您要使用像 UaModeler 这样的工具并在其中创建自定义结构,然后查看生成的 XML,您会发现有一大堆其他支持节点与之配套。

当这些东西到位时,客户可以在事先不知道它们的情况下学习如何解码自定义结构。Milo 的客户端也包含此功能。

此外,首先,您应该通过制作一个来对结构数组进行编码ExtensionObject[],每个结构都包含ExtensionObject一个标量结构值。

于 2018-09-27T13:40:18.697 回答