简体   繁体   English

如何在 milo opc ua 中正确使用 ExtensionObject 和 Struct

[英]How to correctly work with ExtensionObject and Struct in milo opc ua

I would like to ask how should I work correctly with Struct when I am trying to read some object from opc ua server.我想问一下当我试图从 opc ua 服务器读取一些对象时,我应该如何正确地使用 Struct。 I went trough this example and I was able to read the data.我通过了这个例子,我能够读取数据。

But right now I don't know how to correctly read them.但现在我不知道如何正确阅读它们。 Let's imagine I am reading some datastructure including two arrays for x and y values.假设我正在读取一些数据结构,包括 x 和 y 值的两个数组。 I tried to do something like this:我试图做这样的事情:

 Float[] x = (Float[])struct.getMember("x").getValue()
 Float[] y = (Float[])struct.getMember("y").getValue()

but I receive exception "Cannot cast 'java.lang.Object[]' to 'java.lang.Float[]'" I am able to do it this way:但我收到异常“无法将 'java.lang.Object[]' 转换为 'java.lang.Float[]'” 我可以这样做:

float[] x = new float[100];
        int i = 0;
        for(Object o: (Object[])struct.getMember("x").getValue()){
            x[i] = (Float)o;
            i++;
        }

but I don't think this could be right.但我不认为这可能是对的。

Anyway I would like to achieve something similar like reading json file with jackson.无论如何,我想实现类似的东西,比如用 jackson 读取 json 文件。 To have some class with same naming asi the "members are and with suitable types and do something like:要拥有一些与“成员相同”的类,并且具有合适的类型,然后执行以下操作:

OpcuaReader reader = ...
MyClass myClass = reader.read(struct, MyClass.class)

I could be totally wrong so could anyone suggest me how should I solve such problem?我可能完全错了,所以有人可以建议我应该如何解决这样的问题吗?

First of all, you cannot cast array of objects like that.首先,你不能像这样投射对象数组。 Instead, you could use the stream API to construct Floats like this:相反,您可以使用流 API 来构造 Floats,如下所示:

Object[] objectArray = { 1.0f, 2.0f, 3, 4, 5 };
Float floatArray[] = Arrays.stream(objectArray)
  .map(Object::toString)
  .map(Float::valueOf)
  .toArray(Float[]::new);

About the Milo client, there is a great example of reading custom data types in ReadWriteCustomDataTypeNodeExample .关于 Milo 客户端,在ReadWriteCustomDataTypeNodeExample 中有一个很好的读取自定义数据类型的例子。

You can create your own type similar to CustomStructType and override the decode method for yourself.您可以创建自己的类似于CustomStructType的类型并为自己覆盖 decode 方法。 The decoder also has a built in readFloatArray method in hand:解码器还有一个内置的readFloatArray方法:

@Override
public CustomStructType decode(
    SerializationContext context,
    UaDecoder decoder) throws UaSerializationException {

    String foo = decoder.readString("Foo");
    UInteger bar = decoder.readUInt32("Bar");
    boolean baz = decoder.readBoolean("Baz");

    Float[] floatArray = decoder.readFloatArray("floatArray");

    return new CustomStructType(foo, bar, baz);
}

Big thanks to istibekesi , we manage to get it working.非常感谢istibekesi ,我们设法让它工作。 For someone who would have same problem here is what you need to do:对于在这里遇到同样问题的人,您需要做的是:

1) Find the TYPE_ID 1) 找到 TYPE_ID

  • you need to find the NamespaceIndex and Identifier of the DataType of the structure (object) you want to read over OPC UA using for example UaExpert您需要使用例如UaExpert 找到要通过 OPC UA 读取的结构(对象)的数据类型的 NamespaceIndex 和标识符
  • if you are not sure which DataType it is just find some variable representing this structure and there you will see the DataType info on the right side of the screen when you click on it.如果您不确定是哪种数据类型,它只是找到一些代表此结构的变量,当您单击它时,您将在屏幕右侧看到数据类型信息。

2) Find the BINARY_ENCODING_ID 2) 找到 BINARY_ENCODING_ID

  • to find this one you need to search for the DataType itself using UaExpert it will be some were under Types/DataTypes ...要找到这个,您需要使用 UaExpert 搜索 DataType 本身,它会在 Types/DataTypes 下...
  • when you find it click on it for more info当你找到它时,点击它以获取更多信息
  • then on the right bottom part of your screen there will be "HasEncoding|Default Binary" and you double click on it然后在屏幕的右下角将出现“HasEncoding|Default Binary”,然后双击它
  • this way you will receive the NamespaceIndex and the Identifier for BINARY_ENCODING_ID这样您将收到 NamespaceIndex 和 BINARY_ENCODING_ID 的标识符

3) Follow this example 3)按照这个例子

  • To have all parts of milo you need you will need to include sdk-client , dictionary-reader , bsd-parser in your dependencies要拥有您需要的所有 milo 部分,您需要在依赖项中包含sdk-clientdictionary-readerbsd-parser
  • create class similar to this:创建类似于此的类:
public class OpcuaCurve implements UaStructure {

    public static final ExpandedNodeId TYPE_ID = ExpandedNodeId.parse("ns=3;s=DT_\"PrServo_typeRuntimeDriveDiagnosticsProcessValuesTrends\".\"hmiTrend\"");

    public static final ExpandedNodeId BINARY_ENCODING_ID = ExpandedNodeId.parse("ns=3;s=TE_\"PrServo_typeRuntimeDriveDiagnosticsProcessValuesTrends\".\"hmiTrend\"");

    private final Float[] torque;
    private final Float[] speed;

    public OpcuaCurve() {
        this(null, null);
    }

    public OpcuaCurve(Float[] torque, Float[] speed) {
        this.torque = torque;
        this.speed = speed;
    }

    public Float[] getSpeed() {
        return speed;
    }

    public Float[] getTorque() {
        return torque;
    }

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

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

    @Override
    public ExpandedNodeId getXmlEncodingId() {
        // XML encoding not supported
        return ExpandedNodeId.NULL_VALUE;
    }







    public static class Codec extends GenericDataTypeCodec<OpcuaCurve> {
        @Override
        public Class<OpcuaCurve> getType() {
            return OpcuaCurve.class;
        }

        @Override
        public OpcuaCurve decode(
            SerializationContext context,
            UaDecoder decoder) throws UaSerializationException {

            Float[] torqueArray = decoder.readFloatArray("motorTorque");
            Float[] speedArray = decoder.readFloatArray("motorSpeed");

            return new OpcuaCurve(torqueArray,speedArray);
        }

        @Override
        public void encode(
                SerializationContext context,
                UaEncoder encoder, OpcuaCurve value) throws UaSerializationException {

            encoder.writeFloatArray("motorTorque", value.torque);
            encoder.writeFloatArray("motorTorque", value.speed);
        }
    }

}
  • and in register the decoder to the client like this:并将解码器注册到客户端,如下所示:
private void registerCustomCodec(OpcUaClient client) {
        NodeId binaryEncodingId = OpcuaCurve.BINARY_ENCODING_ID
                .local(client.getNamespaceTable())
                .orElseThrow(() -> new IllegalStateException("namespace not found"));

        // Register codec with the client DataTypeManager instance
        client.getDataTypeManager().registerCodec(
                binaryEncodingId,
                new OpcuaCurve.Codec().asBinaryCodec()
        );
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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