Как правильно написать массив ExtensionObject на сервере Eclipse Milo OpcUa?

Я пытаюсь написать массив ExtensionObject на сервере Eclipse Milo OpcUa. Я делаю все это на Java 8 и на Milo 0.2.3.

Мой способ проверить то, что я написал на свой Сервер, - это клиент Unified Automation 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 я вижу, что значение, включая его метку времени, изменилось, но я не вижу фактическое значение. Значение имеет тип Array для ExtensionObject, и я не могу прочитать ни одно из вложенных значений. Но это то, что я видел в других проектах. У них есть пользовательские структуры, а вложенные поля читаются человеком в UaExpert.

Проблема не изменится, если я сделаю это без массива и просто напишу одну MyStructure.

У вас есть идея, что я делаю неправильно или не делаю вообще?

1 ответ

В настоящее время пользовательские структуры в Milo работают только в том случае, если клиент, читающий / записывающий их, заранее знает о структуре.

То, что вы упускаете (и еще не реализовано в Milo), это вся сложность вокруг создания DataTypeDictionary, регистрации его в адресном пространстве и связывания вашего кодека с записью в этом словаре через DataTypeEncoding.

Если бы вы использовали такой инструмент, как UaModeler, и создали в нем собственную структуру, а затем взглянули на сгенерированный XML, вы бы увидели целую кучу других поддерживающих узлов, которые поддерживают его.

Когда все это происходит, клиенты могут научиться декодировать пользовательские структуры, не зная о них заранее. Клиент Майло включает в себя и эту функциональность.

Кроме того, fwiw, вы должны закодировать ваш массив структур, сделав ExtensionObject[], с каждым ExtensionObject удерживая одно значение скалярной структуры.

Другие вопросы по тегам