mikakaraila / node-red-contrib-opcua

A Node-RED node to communicate OPC UA. Uses node-opcua library.
Other
214 stars 196 forks source link

Write Multiple no longer works #740

Closed MMBud21 closed 1 week ago

MMBud21 commented 1 week ago

Hi Mika, Unfortunately the problem from issue #723 with WriteMultiple has not yet been resolved.

@apbrauer73 had already tested it. After you closed the post today, I also installed version 0.2.333 and tested it again. It has changed a bit, but it still doesn't work like it did in version 0.2.330. 333

The following behavior has changed, which makes even less sense to me than before.

If I write anything other than "writemultiple" in the topic, the values ​​arrive perfectly in the Siemens PLC. However, every time I send something, I get the error: "Client node error on: Write_Multiple error: ["Write multiple items session is not active!"]" and in the debug your client also gives the message status: "invalid session". But you can see at the very bottom of the debug that your OPC client node then gives the value 0 (successfully written) for both variables. The values ​​arrive in the PLC, but that's no use if all the error messages are written every time. Multiple

However, if I write "writemultiple" in the topic, as you specify, the following error message appears: "Client node error on: Write_Multiple error: ["Write_Multiple no items to write"]" and therefore no more values ​​are written to the PLC. Accordingly, no feedback is received in the debug and only the message status: "no items to write" is displayed. WriteMultiple

Why is it that it hasn't worked since version 0.2.330? You can see the structure of my two arrays in full in the debug, if you can identify an error. I have also tested it on several systems and even completely reinstalled Node-RED on one of them.

apbrauer73 commented 1 week ago

Hi @MMBud21, I decided to rewrite my flow to loop though each item to send to the OPCUA node: image

I used this palette for the loop node: image

This is my flow

[ { "id": "133ddcfda9be9a1b", "type": "inject", "z": "4395b51eaabeb2f9", "name": "Set Alarms", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "str", "x": 380, "y": 220, "wires": [ [ "e07bca2a7b335291" ] ] }, { "id": "e07bca2a7b335291", "type": "function", "z": "4395b51eaabeb2f9", "name": "Set Alarm tags", "func": "msg.payload = [];\nmsg.topic = \"writemultiple\";\n\nmsg.payload[0] = \n{\n nodeId: \"ns=2;s=RCV_CC394_SPS_.RCV_CC394_SPS.CC394_U452050_PE_FD\",\n datatype: \"Boolean\",\n value: false\n};\n\nmsg.payload[1] = \n{\n nodeId: \"ns=2;s=RCV_CC394_SPS_.RCV_CC394_SPS.CC394_U452010_PE_FD\",\n datatype: \"Boolean\",\n value: false\n};\n\nmsg.payload[2] =\n{\n nodeId: \"ns=2;s=RCV_CC394_SPS_.RCV_CC394_SPS.CC394_U451700_PE_FD\",\n datatype: \"Boolean\",\n value: false\n};\n\nmsg.payload[3] =\n{\n nodeId: \"ns=2;s=RCV_CC394_SPS_.RCV_CC394_SPS.CC394_U452020_PE_FD\",\n datatype: \"Boolean\",\n value: false\n};\n\nmsg.payload[4] =\n{\n nodeId: \"ns=2;s=RCV_CC394_SPS_.RCV_CC394_SPS.CC394_DEV_ENET\",\n datatype: \"UInt16\",\n value: 0\n};\n\nreturn msg;", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 580, "y": 220, "wires": [ [ "efac4e3500ab452e", "06eaaa2ccd1fad5b" ] ] }, { "id": "efac4e3500ab452e", "type": "debug", "z": "4395b51eaabeb2f9", "name": "Set debug", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 750, "y": 120, "wires": [] }, { "id": "06eaaa2ccd1fad5b", "type": "loop", "z": "4395b51eaabeb2f9", "name": "", "kind": "enum", "count": "", "initial": "1", "step": "1", "condition": "", "conditionType": "js", "when": "before", "enumeration": "payload", "enumerationType": "msg", "limit": "", "loopPayload": "loop-val", "finalPayload": "final-last", "x": 910, "y": 220, "wires": [ [], [ "439ce26299387816" ] ] }, { "id": "580867f9b12a99b6", "type": "debug", "z": "4395b51eaabeb2f9", "name": "loop output", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 1390, "y": 240, "wires": [] }, { "id": "439ce26299387816", "type": "function", "z": "4395b51eaabeb2f9", "name": "Loop Func", "func": "\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 890, "y": 320, "wires": [ [ "06eaaa2ccd1fad5b", "ba60a427611c56ce" ] ] }, { "id": "7f6bc79ee4a56240", "type": "OpcUa-Client", "z": "4395b51eaabeb2f9", "endpoint": "b37371af99e005b7", "action": "write", "deadbandtype": "a", "deadbandvalue": 1, "time": 10, "timeUnit": "s", "certificate": "n", "localfile": "", "localkeyfile": "", "securitymode": "None", "securitypolicy": "None", "useTransport": false, "maxChunkCount": "", "maxMessageSize": "", "receiveBufferSize": "", "sendBufferSize": "", "name": "Kepware Write", "x": 1400, "y": 320, "wires": [ [], [] ] }, { "id": "ba60a427611c56ce", "type": "change", "z": "4395b51eaabeb2f9", "name": "Update payload", "rules": [ { "t": "set", "p": "topic", "pt": "msg", "to": "payload.nodeId", "tot": "msg", "dc": true }, { "t": "set", "p": "datatype", "pt": "msg", "to": "payload.datatype", "tot": "msg", "dc": true }, { "t": "set", "p": "payload", "pt": "msg", "to": "payload.value", "tot": "msg", "dc": true } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 1160, "y": 320, "wires": [ [ "7f6bc79ee4a56240", "580867f9b12a99b6" ] ] }, { "id": "b37371af99e005b7", "type": "OpcUa-Endpoint", "endpoint": "opc.tcp://192.168.51.127:49320", "secpol": "None", "secmode": "None", "none": true, "login": false, "usercert": false, "usercertificate": "", "userprivatekey": "" } ]

This is my workaround until this gets resolved, I hope it helps.

mikakaraila commented 1 week ago

Ok, I will recheck what could cause this...

Now I saw that you have there "no items to write" as node status. This helps me to look case.

mikakaraila commented 1 week ago

Found it, wrong error handler.

apbrauer73 commented 1 week ago

@mikakaraila , I just tried 0.2.334 and I still get error "no items to write". Is this the correct payload format for the Write multiple?

`msg.payload = []; msg.topic = "writemultiple";

msg.payload[0] = { nodeId: "ns=2;s=RCV_CC394SPS.RCV_CC394_SPS.CC394_U452050_PE_FD", datatype: "Boolean", value: false };

msg.payload[1] = { nodeId: "ns=2;s=RCV_CC394SPS.RCV_CC394_SPS.CC394_U452010_PE_FD", datatype: "Boolean", value: false };

msg.payload[2] = { nodeId: "ns=2;s=RCV_CC394SPS.RCV_CC394_SPS.CC394_U451700_PE_FD", datatype: "Boolean", value: false };

msg.payload[3] = { nodeId: "ns=2;s=RCV_CC394SPS.RCV_CC394_SPS.CC394_U452020_PE_FD", datatype: "Boolean", value: false };

msg.payload[4] = { nodeId: "ns=2;s=RCV_CC394SPS.RCV_CC394_SPS.CC394_DEV_ENET", datatype: "UInt16", value: 0 };

return msg;`

I just wonder if you changed the payload format in the update.

apbrauer73 commented 1 week ago

I think the issue is in this piece of code to build the array but I don't see how it will work if the message topic is "writemultiple".

 if (msg.topic !== "writemultiple" && msg.topic !== "clearitems") {
   let opcuaDataValue = opcuaBasics.build_new_dataValue(msg.datatype, msg.payload);

   let item = {
     nodeId: msg.topic,
     datatype: msg.datatype,
     attributeId: opcua.AttributeIds.Value,
     indexRange: null,
     value: new opcua.DataValue({ value: opcuaDataValue })
   };

   item.value.sourceTimestamp = new Date(msg.timestamp).getTime();
   verbose_log("ITEM: " + stringify(item));

   writeMultipleItems.push(item); // This is where the item is added to the array.
 }

I wonder if it should be like this....

if (msg.topic === "writemultiple" && Array.isArray(msg.payload)) {
  msg.payload.forEach(payloadItem => {
    let opcuaDataValue = opcuaBasics.build_new_dataValue(payloadItem.datatype, payloadItem.value);

 let item = {
      nodeId: payloadItem.nodeId,
      datatype: payloadItem.datatype,
      attributeId: opcua.AttributeIds.Value,
      indexRange: null,
      value: new opcua.DataValue({ value: opcuaDataValue })
    };

   item.value.sourceTimestamp = new Date(msg.timestamp).getTime();
   verbose_log("ITEM: " + stringify(item));

   writeMultipleItems.push(item); // Add each item from the payload to writeMultipleItems
  });
}
MMBud21 commented 1 week ago

I also tested it. The one error "Client node error on: Write_Multiple error: ["Write multiple items session is not active!"]" that I described above is gone. It now works perfectly for me if I write anything in the topic, just not "writemultiple".

I think @apbrauer73 is right, it's just that the negation at writemultiple is wrong:

if (msg.topic !== "writemultiple" && msg.topic !== "clearitems") { let opcuaDataValue = opcuaBasics.build_new_dataValue(msg.datatype, msg.payload);

mikakaraila commented 1 week ago

It will add msg into the nodesToWrite, normally it should add items one by one. But if payload is an Array it expects that can be used. There is also topic clearitems to clean array.

MMBud21 commented 1 week ago

That sounds like a good solution. In any case, the comparison msg.topic !== "writemultiple" must be adjusted to "===". Because currently sending works fine with every topic and without error messages, just not with the topic "writemultiple" :).

nikolaioak commented 1 week ago

It seems along with this issue and subsequent fix (v0.2.334) there were a number of console.log() entries left for debugging within 102-opcuaclient.js and makes my Node-RED logs unusable since I use writemultiple for some heartbeat tags between systems. Can the logging be evaluated/removed?

apbrauer73 commented 1 week ago

I just tried changing the topic to something other than "writemultiple" and it worked like it did for @MMBud21. @mikakaraila when you fix this also correct the status message, I noticed that when I trigger the multiple write the node is stuck with the status "active writing".

image

mikakaraila commented 1 week ago

Cleanup console and set status to values written (green). Comparison cannot be changed as it will break the other way to use writemultiple.

mikakaraila commented 1 week ago

I am really tired and busy at work I hope this will be enough for a while...

MMBud21 commented 1 week ago

Good morning @mikakaraila, I just tested it with version 0.2.335. Version

It only works with all topics, just not with "writemultiple". But if you know that, it's not a problem. As you can see in the screenshots, it works perfectly with the topic "whateverIwant".

I think a lot of people are now using your client for some important applications and if basic functions like WriteMultiple no longer work after an update, that's obviously annoying. But of course we all know that you do this in your free time and certainly don't always have the time or inclination to fix the errors. Thank you very much for your efforts and have a good day at work :).

Topic = "writemultiple" writemultiple

Topic = "whateverIwant" whateveriwant

MMBud21 commented 1 week ago

Hey @mikakaraila, I looked at your code for WriteMultiple in the 102-opcuaclient.js myself and am relatively sure that I have found the problem.

It currently works if we do not use the topic "writemultiple". Your comparisons above were correct, however, so at first I could not understand how this is possible. Then I changed the debug messages and found that we are not using the "new code" for communication.

Directly below there is another query that you called the "OLD original way". I also adjusted the debug messages there and lo and behold, this communication is currently being used. Because there is also no query there as to whether the topic is "writemultiple".

oldway

useold The data is written, I think the dot is just not green because you set the color somewhere when the text is "values ​​written". When I changed it to "values ​​written old" the dot is red, but the function is OK. I didn't look any further at where it sets the color, but it doesn't matter.

Then I looked into why the error "no items to write" always occurs with the topic "writemultiple". The problem is probably that you only fill the array in the upper part (red box, orange arrow), which is only processed if the topic is not "writemultiple" and payload is not an array.

In the lower part (green box) you first check whether the array has items. If that is not the case (length === 0), the message we get appears.

To test it, I deactivated the old part and filled the array in the green part with data before checking what length it has. After that it works perfectly with "writemultiple" but no longer works with all other topics, as it should.

newway