Skip to main content

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

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

Back to the top