简体   繁体   中英

How do I properly write an ExtensionObject Array on an Eclipse Milo OpcUa Server?

I am trying to write an Array of ExtensionObject on an Eclipse Milo OpcUa Server. I'm doing all this in Java 8 and on Milo 0.2.3.

My way to test what I wrote to my Server is the Unified Automation UaExpert Client and a little Python client. Both show the same results.

I have the following Structure (I named it MyStructure for this scenario). It is already present as an Array and I want to write it to the respective node.

@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());
        }
    }
}

I write the node like this, where node is an instance of UaVariableNode and array my Array object, which I created like this:

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));
}

I registered MyStructure definition beforehand like this:

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

Whenever I set my node, the server doesn't complain. It actually sets something, to be precise it sets 42 Extension Objects. In UaExpert I see that the value, including its timestamp, changed, but I can't see the actual value. The value is just of the type Array of ExtensionObject and I can't read any of the nested values. But that is what I saw in other projects. They have custom structures, and the nested fields are human readable in UaExpert.

The problem doesn't change if I do it without the Array and just write one MyStructure.

Do you have an idea, what I am doing wrong or not doing at all?

Right now custom structures in Milo only work if the client reading/writing them knows about the structure in advance.

What you're missing (and isn't implemented by Milo yet) is all the complexity around creating a DataTypeDictionary, registering it in the address space, and linking your codec to an entry in that dictionary via a DataTypeEncoding.

If you were to use a tool like UaModeler and create a custom structure in it, then take a look at the generated XML, you'd see there's a whole bunch of other supporting nodes that go along with it.

When these things are in place, clients can learn how to decode custom structures without knowing about them in advance. Milo's client includes this functionality as well.

Also, fwiw, you should encode your array of structures by making an ExtensionObject[] , with each ExtensionObject holding one scalar structure value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM