Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [milo-dev] encoding ResultDataType

> But what is the relation between being "allow subtype" and encoding it? 

It means the actual object that you decode may not be a ResultMetaDataType, it may be a subclass of that. So if you don't account for that somehow you may not decode the right kind of object.

> what do you mean by  "decode an ExtensionObject and then further decode that" 

I think just use `UaDecoder::readExtensionObject`, and then further try to decode that ExtensionObject via `ExtensionObject::decode`.

I think you're in a little over your head for being in strictly unsupported territory.

On Mon, Jul 29, 2024 at 8:38 AM Francesco Viscomi <fviscomi@xxxxxxxxx> wrote:
Hi Kevin,
some clarification you sed "`resultMetaData` field is declared as "Allow Subtypes" may be because :
image.png

But what is the relation between being "allow subtype" and encoding it? 

And second, what do you mean by  "decode an ExtensionObject and then further decode that" 

thx for your help.


Il giorno lun 29 lug 2024 alle ore 16:46 Kevin Herron <kevinherron@xxxxxxxxx> ha scritto:
This is a deceptively complex structure because both fields are abstract. At the moment I'm not sure what decoding it would look like.

There should be two fields in the datatype:
  private final ResultMetaDataType resultMetaData;

  private final Variant @Nullable [] resultContent;

What makes this complex is that the `resultMetaData` field is declared as "Allow Subtypes", so I think you have to decode an ExtensionObject and then further decode that, casting it to `ResultMetaDataType`.

The `Variant[]` field should be easy to decode as there is a method directly on `UaDecoder`. These fields are not optional so you don't need the encoding mask stuff.

I don't have any examples, I have not dealt with a structure like this, nor tried to generate/write code for one.

On Mon, Jul 29, 2024 at 2:19 AM Francesco Viscomi via milo-dev <milo-dev@xxxxxxxxxxx> wrote:
Hi all, Kevin

I'm going to decode the structure ResultDataType:
image.png


Is there an example of encoding that kind of structure?I'm not able do to it by myself!

This what I did
1. create the ResultDataType

public class ResultDataType extends Structure implements UaStructure {

               

                 public static final ExpandedNodeId TYPE_ID = ExpandedNodeId.parse("nsu=http://opcfoundation.org/UA/Machinery/Result/;i=3008");

                //public static final ExpandedNodeId TYPE_ID = ExpandedNodeId.parse("nsu=ns=5;i=3008");

 

                 public static final ExpandedNodeId XML_ENCODING_ID = ExpandedNodeId.parse("nsu=http://opcfoundation.org/UA/;i=12676");

 

                 public static final ExpandedNodeId BINARY_ENCODING_ID = ExpandedNodeId.parse("nsu=http://opcfoundation.org/UA/Machinery/Result/;i=5008");

                // public static final ExpandedNodeId BINARY_ENCODING_ID = ExpandedNodeId.parse("nsu=ns=5;i=5008");

                 

                 

                 private final ResultMetaDataType resultMetaDataType;

 

 

                public ResultDataType(ResultMetaDataType resultMetaDataType) {

                                super();

                                this.resultMetaDataType = resultMetaDataType;

                }

                 

 

                  @Override

                    public ExpandedNodeId getTypeId() {

                        return TYPE_ID;

                    }

 

                    @Override

                    public ExpandedNodeId getXmlEncodingId() {

                        return XML_ENCODING_ID;

                    }

 

                    @Override

                    public ExpandedNodeId getBinaryEncodingId() {

                        return BINARY_ENCODING_ID;

                    }

 

 

                                public ResultMetaDataType getResultMetaDataType() {

                                                return resultMetaDataType;

                                }

                   

                                 public static final class Codec extends GenericDataTypeCodec<ResultDataType> {

                                        @Override

                                        public Class<ResultDataType> getType() {

                                            return ResultDataType.class;

                                        }

 

                                        @Override

                                        public ResultDataType decode(SerializationContext context, UaDecoder decoder) {

                                                System.out.println("decode ResultDataType ");

                                               

                                                String ResultId = null;

                                                UInteger encodingMask = decoder.readUInt32("EncodingMask");

                                                long encodingMaskValue = encodingMask.longValue();

                                               

                                                if ((encodingMaskValue & (1L << 0)) != 0) {

                                                                ResultId = decoder.readString("ResultId");

                                            }

                                                System.out.println("ResultId "+ResultId);

                                                               

                                                ResultMetaDataType r = new ResultMetaDataType("resultId");

                                               

                                                return new ResultDataType(r);

                                        }

 

                                                                @Override

                                                                public void encode(SerializationContext context, UaEncoder writer,

                                                                                                ResultDataType value) throws UaSerializationException {

                                                                               

                                                                                              System.out.println("encode ResultMetaDataType ");

                                                                               

                                                                               

                                                                                             long encodingMaskValue = 0L;

                                                                                              if (value.resultMetaDataType != null) {

                                                                                                       encodingMaskValue |= (1L << 0);

                                                                                              }

 

 

                                                                                          writer.writeUInt32("EncodingMask", Unsigned.uint(encodingMaskValue));

                                           

                                                                                         if (value.resultMetaDataType != null) {

                                                                                                  //writer.writeString("ResultId", value.ResultId);

                                                                                                 writer.writeStruct("ResultMetaDataType", value, ResultDataType.BINARY_ENCODING_ID);

                                                                                       //writer.writeStruct("ResultMetaDataType", value,new ResultDataType.Codec().asBinaryCodec() );

                                                                                  }                                                  

                                                                               

                                                                }

                                    }

                 

                 

 

}


2. the previous class has as member the class ResultMetaDataType

public class ResultMetaDataType extends Structure implements UaStructure {

                               

                                 public static final ExpandedNodeId TYPE_ID = ExpandedNodeId.parse("nsu=http://opcfoundation.org/UA/Machinery/Result/;i=3007");

 

                                 public static final ExpandedNodeId XML_ENCODING_ID = ExpandedNodeId.parse("nsu=http://opcfoundation.org/UA/;i=12676");

 

                                 public static final ExpandedNodeId BINARY_ENCODING_ID = ExpandedNodeId.parse("nsu=http://opcfoundation.org/UA/Machinery/Result/;i=5005");

                                 

                                 private final String ResultId;

 

                                public ResultMetaDataType(String resultId) {

                                                super();

                                                ResultId = resultId;

                                }

                                 

                                 @Override

                                    public ExpandedNodeId getTypeId() {

                                        return TYPE_ID;

                                    }

 

                                    @Override

                                    public ExpandedNodeId getXmlEncodingId() {

                                        return XML_ENCODING_ID;

                                    }

 

                                    @Override

                                    public ExpandedNodeId getBinaryEncodingId() {

                                        return BINARY_ENCODING_ID;

                                    }

                                   

                                   

                                                public String getResultId() {

                                                                return ResultId;

                                                }

                                 

                                               

                                                 public static final class Codec extends GenericDataTypeCodec<ResultMetaDataType> {

                                                        @Override

                                                        public Class<ResultMetaDataType> getType() {

                                                            return ResultMetaDataType.class;

                                                        }

 

                                                        @Override

                                                        public ResultMetaDataType decode(SerializationContext context, UaDecoder decoder) {

                                                               

                                                                System.out.println("decode ResultMetaDataType ");

                                                               

                                                                String ResultId = null;

                                                                UInteger encodingMask = decoder.readUInt32("EncodingMask");

                                                                long encodingMaskValue = encodingMask.longValue();

                                                               

                                                                if ((encodingMaskValue & (1L << 0)) != 0) {

                                                                                ResultId = decoder.readString("ResultId");

                                                            }

                                                                System.out.println("ResultId "+ResultId);

                                                               

                                                                return new ResultMetaDataType(ResultId);

                                                        }

 

 

 

                                                                                @Override

                                                                                public void encode(SerializationContext context, UaEncoder writer,

                                                                                                                ResultMetaDataType value) throws UaSerializationException {

                                                                                               

                                                                                                System.out.println("encode ResultMetaDataType ");

                                                                                               

                                                                                               

                                                                                                long encodingMaskValue = 0L;

                                                            if (value.ResultId != null) {

                                                                encodingMaskValue |= (1L << 0);

                                                            }

 

                                                            writer.writeUInt32("EncodingMask", Unsigned.uint(encodingMaskValue));

                                                           

                                                            if (value.ResultId != null) {

                                                               writer.writeString("ResultId", value.ResultId);

                                                            }

                                                                                               

                                                                                }

                                                    }

}



3. in the handler:

public class GetLatestResult extends AbstractMethodInvocationHandler{

 

                private boolean hasError;

               

                public GetLatestResult(UaMethodNode node,boolean hasError) {

                                super(node);

                                this.hasError=hasError;

                }

 

               

    public static final Argument TimeOut = new Argument(

            "TimeOut",

            Identifiers.Int32,

            ValueRanks.Scalar,

            null,

            new LocalizedText("The argument for TimeOut.")

        );

               

   

   

    //output

    public static final Argument ResultHandle = new Argument(

            "ResultHandle",

            Identifiers.String,

            ValueRanks.Scalar,

            null,

            new LocalizedText("The argument for ResultHandle")

        );

   

    public static final Argument ResultDataType = new Argument(

            "ResultDataType",

            Identifiers.Structure,

            ValueRanks.Scalar,

            null,

            new LocalizedText("The argument to ResultDataType.")

        );

   

    public static final Argument Error = new Argument(

            "Error",

            Identifiers.Int32,

            ValueRanks.Scalar,

            null,

            new LocalizedText("The argument to Error.")

        );

   

   

               

                @Override

                public Argument[] getInputArguments() {

                                return new Argument[] {TimeOut};

                }

 

                @Override

                public Argument[] getOutputArguments() {

                                return new Argument[] {ResultHandle,ResultDataType,Error};

                }

 

                @Override

                protected Variant[] invoke(InvocationContext invocationContext, Variant[] inputValues) throws UaException {

 

                                System.out.println("invoke GetLatestResult has error: " + hasError);

                               

                               

                                 @SuppressWarnings("removal")

                                 Integer resultHandle = new Integer(22);

                                 Integer error = new Integer(22);

               

 

                                 

                                 ResultMetaDataType rMDt = new ResultMetaDataType("resultIdd");

                                 

                                 ResultDataType rDT = new ResultDataType(rMDt);

                                 

                                 LocalizedText stMessage = new LocalizedText("status message");

                                 

                                 Variant var = new Variant(rDT);

 

                                return new Variant[]{new Variant(resultHandle),var,new Variant(error)};

 

                }

}


There is no way to have the value returned by the method invoke, when the platform call the encoding method it give me error:

In the class ResultDataType in the method encode: 
  • if I use writer.writeStruct("ResultMetaDataType", value,new ResultDataType.Codec().asBinaryCodec() ); I get:

09:44:58.300 [milo-shared-thread-pool-8] WARN  o.e.m.o.stack.core.util.TaskQueue - Uncaught Throwable during Task execution.
java.lang.StackOverflowError: null
at java.base/sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(UTF_8.java:456)
at java.base/sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:564)
at java.base/java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:585)
at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:293)
at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:282)
at java.base/sun.nio.cs.StreamEncoder.write(StreamEncoder.java:132)
at java.base/java.io.OutputStreamWriter.write(OutputStreamWriter.java:205) 


  • If I use writer.writeStruct("ResultMetaDataType", value, ResultDataType.BINARY_ENCODING_ID); I get 
09:53:20.272 [milo-shared-thread-pool-1] ERROR o.e.m.o.s.s.t.u.UascServerSymmetricHandler - Error serializing response: StatusCode{name=Bad_EncodingError, value=0x80060000, quality=bad}
org.eclipse.milo.opcua.stack.core.UaSerializationException: no codec registered: NodeId{ns=5, id=5008}
at org.eclipse.milo.opcua.stack.core.serialization.OpcUaBinaryStreamEncoder.writeStruct(OpcUaBinaryStreamEncoder.java:938)
at org.eclipse.milo.opcua.stack.core.serialization.OpcUaBinaryStreamEncoder.writeStruct(OpcUaBinaryStreamEncoder.java:958)
at org.eclipse.milo.opcua.stack.core.types.structured.ResultDataType$Codec.encode(ResultDataType.java:116)




Even if I have registered the codec in dataTypeInizializer; 
So what is wrong with this? Also is it possible to encoding a well known structure that contains another structure?
--
Ing. Viscomi Francesco
_______________________________________________
milo-dev mailing list
milo-dev@xxxxxxxxxxx
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/milo-dev


--
Ing. Viscomi Francesco

Back to the top