Как правильно написать массив 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.

У вас есть идеи, что я делаю не так или не делаю совсем?


person Timo Stone    schedule 27.09.2018    source источник


Ответы (1)


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

То, что вам не хватает (и еще не реализовано Майло), - это вся сложность, связанная с созданием DataTypeDictionary, его регистрацией в адресном пространстве и привязкой вашего кодека к записи в этом словаре через DataTypeEncoding.

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

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

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

person Kevin Herron    schedule 27.09.2018
comment
Спасибо за информацию! Это в планах Майло? - person Timo Stone; 28.09.2018
comment
да. В ближайшем будущем вы сможете импортировать NodeSet, сгенерированные инструментами моделирования для создания словаря, а чуть дальше (когда будет реализован UA 1.04), вероятно, можно будет также определять их вручную, потому что 1.04 добавляет упрощенный способ для определения типов данных. - person Kevin Herron; 28.09.2018