簡體   English   中英

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

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

我想問一下當我試圖從 opc ua 服務器讀取一些對象時,我應該如何正確地使用 Struct。 我通過了這個例子,我能夠讀取數據。

但現在我不知道如何正確閱讀它們。 假設我正在讀取一些數據結構,包括 x 和 y 值的兩個數組。 我試圖做這樣的事情:

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

但我收到異常“無法將 '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++;
        }

但我不認為這可能是對的。

無論如何,我想實現類似的東西,比如用 jackson 讀取 json 文件。 要擁有一些與“成員相同”的類,並且具有合適的類型,然后執行以下操作:

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

我可能完全錯了,所以有人可以建議我應該如何解決這樣的問題嗎?

首先,你不能像這樣投射對象數組。 相反,您可以使用流 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);

關於 Milo 客戶端,在ReadWriteCustomDataTypeNodeExample 中有一個很好的讀取自定義數據類型的例子。

您可以創建自己的類似於CustomStructType的類型並為自己覆蓋 decode 方法。 解碼器還有一個內置的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);
}

非常感謝istibekesi ,我們設法讓它工作。 對於在這里遇到同樣問題的人,您需要做的是:

1) 找到 TYPE_ID

  • 您需要使用例如UaExpert 找到要通過 OPC UA 讀取的結構(對象)的數據類型的 NamespaceIndex 和標識符
  • 如果您不確定是哪種數據類型,它只是找到一些代表此結構的變量,當您單擊它時,您將在屏幕右側看到數據類型信息。

2) 找到 BINARY_ENCODING_ID

  • 要找到這個,您需要使用 UaExpert 搜索 DataType 本身,它會在 Types/DataTypes 下...
  • 當你找到它時,點擊它以獲取更多信息
  • 然后在屏幕的右下角將出現“HasEncoding|Default Binary”,然后雙擊它
  • 這樣您將收到 NamespaceIndex 和 BINARY_ENCODING_ID 的標識符

3)按照這個例子

  • 要擁有您需要的所有 milo 部分,您需要在依賴項中包含sdk-clientdictionary-readerbsd-parser
  • 創建類似於此的類:
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);
        }
    }

}
  • 並將解碼器注冊到客戶端,如下所示:
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