Skip to content

Conversation

danielpeintner
Copy link
Member

@danielpeintner danielpeintner commented Jun 25, 2025

provides a workaround for #1400, but does not really fix the issue.

@danielpeintner danielpeintner requested a review from relu91 as a code owner June 25, 2025 08:12
@danielpeintner danielpeintner marked this pull request as draft June 25, 2025 08:12
@@ -258,7 +258,7 @@ export const theOpcuaJSONCodec = new OpcuaJSONCodec();

export class OpcuaBinaryCodec implements ContentCodec {
getMediaType(): string {
return "application/opcua+octet-stream"; // see Ege
return "application/opcua+octet-stream";
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a left-over I would like to remove

@relu91
Copy link
Member

relu91 commented Jun 26, 2025

I found this workaround quite sneaky... I'm wondering if you have looked here? It seems that the library is not following our architectural pattern. Instead of defining a serdes, he manually takes care of payload serialization and deserialization. Looking in the code base, it seemed that at the time he couldn't find a way to properly register his custom serdes, we should re-evaluate this, and if not possible, we should update the content handling.

@danielpeintner
Copy link
Member Author

We quickly discussed some possible solutions in the committer call and we were wondering whether the contentTypes used so far

  • application/opcua+json
  • application/opcua+octet-stream

are actually right. Should it be with or without opcua+ prefix

@sebastiankb ?

@danielpeintner
Copy link
Member Author

I have been looking into the code more closely and it seems the node-opcua library call of session.read(...) to retrieve a property value.

i.e.,

const dataValue = await session.read({
nodeId,
attributeId: AttributeIds.Value,
});

returns already a JSON structure (see DataValue), even if the value on the wire is binary.

e.g., for dataValue the JSON may look like this

{
    "value": {
        "dataType": "Double",
        "arrayType": "Scalar",
        "value": 1500
    },
    "statusCode": {
        "value": 0
    },
    "sourceTimestamp": "2025-07-01T11:59:50.620Z",
    "sourcePicoseconds": 824200000,
    "serverTimestamp": "2025-07-01T11:59:50.620Z",
    "serverPicoseconds": 824200000
}

The actual value is the double 1500 (in value.value).

The call one line after (on line 314) extracts this value.

return this._dataValueToContent(form, dataValue);

FYI: By default, the two codecs OpcuaBinaryCodec and OpcuaJSONCodec are not even called if no contentType is given. This is the case the binding works nicely.

The whole workflow seems to conflict with what we do in other bindings were we get the raw data and the ContentSerdes converts it if needed (later).

Hence, I see the following options to move on:

  1. We ignore the contentType in the TD and let binding-opcua deal with it (currently implemented in this PR)
  2. We re-code the value to the given contenType (seems weird to me, but we could return dataValue.value.value as is)
  3. We evaluate whether there is anything else we could use besides the JSON structure DataValue. Maybe there is a binary counterpart? I looked a bit around and the expectation is to work with DataValue... but I might be wrong.
  4. Something else ???

Comments are welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants