Fill in array of values when payload data is empty/incorrect

Hi!

I am currently reading 5 different Modbus Slaves and retrieving data and would like to push in "invalid" values whenever there is a connection or error retrieving the data for that specific Modbus slave.

What is a good way of achieving this? This is how my bad/good payload data looks like;

I was thinking of somehow using the quantity property to generate a self defined array[0..quantityNo] and fill this array with "invalid" data numbers, e.g. 65535 on every array element.

In my head I would look at something like:

if (msg.payload = "") then
msg.payload = (generate array0..quantity with invalid data)
else
msg.payload = msg.payload (do nothing)
return msg;

this code above is obviously not functional in anyway but shows how I can think of doing it right now. Would love some examples of how I can achieve my desired function!

Hello Gustav,

I notice from your screenshot, that further down your flow you use the Buffer parser nodes.
How are those nodes configured ? Arent they using the buffer part of the msg msg.responseBuffer.buffer in order to do the conversion to a value ?
My point is, if you go ahead and replace any array values you should be replacing msg.responseBuffer.buffer instead of msg.payload ?

Another question .. where do these values end up ? in a database ? on a dashboard ?
i ask because in my case i read some Modbus values from a few energy meters, saving the data in an Sqlite database and i chose to replace the error values of devices with null

Hi!

I'm using the 1st output of the Modbus Flex Sequencer which outputs an array along with the buffer to the payload. I then use the payload into a Split to split the devices and then I use the buffer parser on the devices and set their variables as global.

The 2nd output from the Modbus Flex Sequencer would probably be used if I were to read the buffer and not the array.

So yes writing the 'invalid' values to the buffer output is what is preferable. I want to write the data to the invalid values on device error/connection error sometime before I publish it as a global.

End goal from there is to take the global data and possibly process the single data before sending it to a production PLC with S7 connection for now, may be expanded upon in the future.


An example of how you solved your swap of data to invalid data would be nice :slight_smile:

In my project i read from many devices sequentially and if there is an error from modbus,
i have enabled the Empty msg on fail .. as you have done :+1:

image

and catch those errors with an "error" Function node after each read

if (msg.payload == "" || msg.hasOwnProperty('error')) {

    global.set("Status.Status_31", "Disconnected")
  
    msg.payload = {

        V_31_L1: null,
        V_31_L2: null,
        V_31_L3: null,
        A_31_L1: null,
        A_31_L2: null,
        A_31_L3: null,
        P_31_L1: null,
        P_31_L2: null,
        P_31_L3: null,
        P_31_T: null,
        S_31_T: null,
        Q_31_T: null,
        PF_31_L1: null,
        PF_31_L2: null,
        PF_31_L3: null,
        F_31_L1: null,
        F_31_L2: null,
        F_31_L3: null
    }

    return [null, msg]
}

else {
    global.set("Status.Status_31", "Connected")
    return [msg, null];
}

In the code sample above im checking if (msg.payload == "" || msg.hasOwnProperty('error'))
and then setting a Context global Status for the device if its Connected or Disconnected (you may not need this). Then in an ugly Javascript way manually (i didnt have much experience with JS when i wrote it)
set each shortname coded value to null. If its valid send it with the first output to Buffer parser and when all msgs arrive JOIN them and then set to global. Else if its an error set to null and send to second output.

You may not find the above useful so if you export and share your flow, we can make recommendations based on your workflow ?

Thank you for the example!

I will try to implement a form of this code.

Below is my current code:

flows (4).json (72.5 KB)

I studied your flow ..
you can use something like this in the Function node

let quantity = msg.quantity   // how many addresses to fill

// if there is error
if (msg.payload == "" || msg.hasOwnProperty('error')) {

    msg.payload = []   // start with empty array 
    
    for (let x = 0; x < quantity; x++) {
        msg.payload.push(65535)  // fill with 65535 
    }
}

return msg;

ps. i wondered before why you used msg.payload in the buffer parsers and not msg.responseBuffer.buffer. After reading the node's help tab it seems both are ok when payload is an array of integer (Int16). my bad.

1 Like

It is definitely preferable to use msg.responseBuffer.buffer (since it is unparsed and therefore doesn't need manipulating into a buffer) but when I wrote the node I was also acutely aware that many/most of the PLC/ModBus nodes return the data parsed as array of integer so made sense to support that. Incidentally, the node also supports a hex string for processing the likes of TCP data e.g e12baec7

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.