Modbus massive reading

Hi everyone.
This is my first experience with Node-Red.

Via node-red-contrib-modus I would like to read N registers of N devices.

I know how to use these nodes to read the various registers individually, but I would like to configure a node that allows me to read about 20 registers for 200 modbus addresses, so I need to develop something that allows me to read this data massively.

[{"id":"c949818599f0f8b2","type":"modbus-flex-getter","z":"91c91236a55d4789","name":"","showStatusActivities":false,"showErrors":false,"showWarnings":true,"logIOActivities":false,"server":"f9b81915cfdec9a4","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":670,"y":860,"wires":[[],["96a0e6a7b6f85015"]]},{"id":"96a0e6a7b6f85015","type":"debug","z":"91c91236a55d4789","name":"debug 8","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":660,"y":920,"wires":[]},{"id":"c695eb0b89f049e3","type":"function","z":"91c91236a55d4789","name":"ModBus","func":"msg.payload = {\n    'fc': 3,\n    'unitid': msg.IDmodbus,\n    'address': msg.VARmodbus,\n    'quantity': 1\n}\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":880,"wires":[["c949818599f0f8b2","96a0e6a7b6f85015"]]},{"id":"b876fd872df8f81f","type":"function","z":"91c91236a55d4789","name":"ID - 6","func":"// Funzione per inviare una variabile tramite il messaggio\nfunction inviaVariabile(msg) {\n    // Imposta la variabile come una proprietà del messaggio\n    msg.IDmodbus = 6;\n\n    // Restituisci il messaggio con la variabile\n    return msg;\n}\n\n// Associa la funzione al nodo di Node-RED\nreturn inviaVariabile(msg);\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":110,"y":880,"wires":[["281308f158516013"]]},{"id":"281308f158516013","type":"function","z":"91c91236a55d4789","name":"VARmodbus","func":"function inviaVariabile(msg) {\n    // Inizializza un array per contenere i set di valori\n    msg.setDiValori = [];\n\n    // Definisci una serie di set di valori\n    var set1 = { VARmodbus: 12030, IDmodbus: msg.IDmodbus };\n    var set2 = { VARmodbus: 12031, IDmodbus: msg.IDmodbus };\n    var set3 = { VARmodbus: 12032, IDmodbus: msg.IDmodbus };\n\n    // Aggiungi i set di valori all'array\n    msg.setDiValori.push(set1);\n    msg.setDiValori.push(set2);\n    msg.setDiValori.push(set3);\n\n\n    // Restituisci il messaggio con le variabili\n    return msg;\n}\n\n// Associa la funzione al nodo di Node-RED\nreturn inviaVariabile(msg);\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":880,"wires":[["c695eb0b89f049e3"]]},{"id":"bb1f50418f5e373a","type":"inject","z":"91c91236a55d4789","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":90,"y":840,"wires":[["b876fd872df8f81f","93828b6750e26982"]]},{"id":"14eb7c1cb9b95917","type":"function","z":"91c91236a55d4789","name":"Array","func":"function inviaVariabile(msg) {\n    // Imposta la variabile come proprietà del messaggio\n\n\n    // Crea un array per contenere le richieste\n    msg.richieste = [];\n\n    // Definisci un array di VARmodbus da utilizzare\n    var varModbusArray = [12030, 12031, 12032];\n\n    // Crea richieste per ciascun VARmodbus\n    for (var i = 0; i < varModbusArray.length; i++) {\n        var richiesta = {\n            fc: 3,\n            unitid: msg.IDmodbus,\n            quantity: 1,\n            VARmodbus: varModbusArray[i],\n            IDmodbus: msg.IDmodbus\n        };\n        msg.richieste.push(richiesta);\n    }\n\n    // Restituisci il messaggio con le variabili\n    return msg;\n}\n\n// Associa la funzione al nodo di Node-RED\nreturn inviaVariabile(msg);\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":940,"wires":[[]]},{"id":"93828b6750e26982","type":"function","z":"91c91236a55d4789","name":"ID - 5","func":"// Funzione per inviare una variabile tramite il messaggio\nfunction inviaVariabile(msg) {\n    // Imposta la variabile come una proprietà del messaggio\n    msg.IDmodbus = 5;\n\n    // Restituisci il messaggio con la variabile\n    return msg;\n}\n\n// Associa la funzione al nodo di Node-RED\nreturn inviaVariabile(msg);\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":110,"y":920,"wires":[["281308f158516013"]]},{"id":"f9b81915cfdec9a4","type":"modbus-client","name":"Tosano - Palesella - Meccaniz.","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"192.168.12.119","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":0,"commandDelay":1,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true}]

This is what I've done so far, but it doesn't work as I expect

THX

I went ahead with the project and developed this method.

The problem is that looking at the debug the data acquisition is not regular every 10 seconds as set by me, every now and then every 30, every now and then a device is not read.

[
    {
        "id": "b5c38da134e475d3",
        "type": "subflow",
        "name": "Schneider NSX Legacy",
        "info": "",
        "category": "Multimetri Schneider",
        "in": [
            {
                "x": 140,
                "y": 320,
                "wires": [
                    {
                        "id": "95020dfee2589cb7"
                    }
                ]
            }
        ],
        "out": [
            {
                "x": 680,
                "y": 320,
                "wires": [
                    {
                        "id": "8d1679d3d5343316",
                        "port": 0
                    }
                ]
            },
            {
                "x": 700,
                "y": 520,
                "wires": [
                    {
                        "id": "5b83c0979c31cc07",
                        "port": 0
                    }
                ]
            }
        ],
        "env": [
            {
                "name": "ModBusID",
                "type": "num",
                "value": "",
                "ui": {
                    "icon": "font-awesome/fa-caret-right",
                    "type": "input",
                    "opts": {
                        "types": [
                            "num"
                        ]
                    }
                }
            }
        ],
        "meta": {
            "module": "Multimetri Z",
            "version": "0.1",
            "author": "ZEnergy"
        },
        "color": "#DEBD5C",
        "outputLabels": [
            "INT16U",
            "Float32"
        ],
        "icon": "node-red-contrib-modbus/modbus-icon.png"
    },
    {
        "id": "19a96cc7d119c3de",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Concatenata L2-L3",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'V23',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12030, \n    'quantity': 1 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 370,
        "y": 120,
        "wires": [
            [
                "8d1679d3d5343316"
            ]
        ]
    },
    {
        "id": "654ad2f8cc5fbbc6",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Concatenata L3-L1",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'V31',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12031, \n    'quantity': 1 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 370,
        "y": 160,
        "wires": [
            [
                "8d1679d3d5343316"
            ]
        ]
    },
    {
        "id": "ca04e754fd3533a7",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Corrente I1",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'I1',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12015, \n    'quantity': 1 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 350,
        "y": 200,
        "wires": [
            [
                "8d1679d3d5343316"
            ]
        ]
    },
    {
        "id": "bd86442faff0272b",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Corrente I2",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'I2',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12016, \n    'quantity': 1 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 350,
        "y": 240,
        "wires": [
            [
                "8d1679d3d5343316"
            ]
        ]
    },
    {
        "id": "6aa8c08714e72f17",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Corrente I3",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'I3',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12017, \n    'quantity': 1 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 350,
        "y": 280,
        "wires": [
            [
                "8d1679d3d5343316"
            ]
        ]
    },
    {
        "id": "66d1ec7e4e56f835",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Potenza Attiva Totale",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'PAT',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12040, \n    'quantity': 1 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 380,
        "y": 320,
        "wires": [
            [
                "8d1679d3d5343316"
            ]
        ]
    },
    {
        "id": "b093a8aa8484f3c3",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Potenza Reattiva Totale",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'PRT',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12044, \n    'quantity': 1 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 390,
        "y": 360,
        "wires": [
            [
                "8d1679d3d5343316"
            ]
        ]
    },
    {
        "id": "efe0172a4cd5e3e0",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Potenza Apparente Totale",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'PApT',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12040, \n    'quantity': 1 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 390,
        "y": 400,
        "wires": [
            [
                "8d1679d3d5343316"
            ]
        ]
    },
    {
        "id": "8fa3d56cefea82dd",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Fattore di Potenza Totale",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'FPT',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12098, \n    'quantity': 1 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 390,
        "y": 440,
        "wires": [
            [
                "8d1679d3d5343316"
            ]
        ]
    },
    {
        "id": "9793859c3b488c2f",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Energia Attiva Totale",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'EAT',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12049, \n    'quantity': 2 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 380,
        "y": 480,
        "wires": [
            [
                "5b83c0979c31cc07"
            ]
        ]
    },
    {
        "id": "96961418ee1c9553",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Energia Reattiva Totale",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'ERT',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12051, \n    'quantity': 2 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 390,
        "y": 520,
        "wires": [
            [
                "5b83c0979c31cc07"
            ]
        ]
    },
    {
        "id": "f2491cdde789dd5a",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Energia Apparente Totale",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'EApT',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12061, \n    'quantity': 2 \n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 390,
        "y": 560,
        "wires": [
            [
                "5b83c0979c31cc07"
            ]
        ]
    },
    {
        "id": "dcfab549a3a4ca9c",
        "type": "function",
        "z": "b5c38da134e475d3",
        "name": "Concatenata L1-L2",
        "func": "let ID = env.get(\"ModBusID\");\n\nmsg.payload = {\n    'value': 'V12',\n    'fc': 3, \n    'unitid': ID, \n    'address': 12029, \n    'quantity': 1\n} \nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 370,
        "y": 80,
        "wires": [
            [
                "8d1679d3d5343316"
            ]
        ]
    },
    {
        "id": "95020dfee2589cb7",
        "type": "junction",
        "z": "b5c38da134e475d3",
        "x": 180,
        "y": 320,
        "wires": [
            [
                "f2491cdde789dd5a",
                "96961418ee1c9553",
                "9793859c3b488c2f",
                "8fa3d56cefea82dd",
                "efe0172a4cd5e3e0",
                "b093a8aa8484f3c3",
                "66d1ec7e4e56f835",
                "6aa8c08714e72f17",
                "bd86442faff0272b",
                "ca04e754fd3533a7",
                "654ad2f8cc5fbbc6",
                "19a96cc7d119c3de",
                "dcfab549a3a4ca9c"
            ]
        ]
    },
    {
        "id": "8d1679d3d5343316",
        "type": "junction",
        "z": "b5c38da134e475d3",
        "x": 580,
        "y": 320,
        "wires": [
            []
        ]
    },
    {
        "id": "5b83c0979c31cc07",
        "type": "junction",
        "z": "b5c38da134e475d3",
        "x": 620,
        "y": 520,
        "wires": [
            []
        ]
    },
    {
        "id": "b9b68b463b4d9325",
        "type": "inject",
        "z": "b456a9d88b9efc5b",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "10",
        "crontab": "",
        "once": true,
        "onceDelay": "10",
        "topic": "",
        "payload": "true",
        "payloadType": "bool",
        "x": 110,
        "y": 700,
        "wires": [
            [
                "1715273a3af8e128",
                "310e3873c2bcce8e"
            ]
        ]
    },
    {
        "id": "340ea44d3e221dfe",
        "type": "debug",
        "z": "b456a9d88b9efc5b",
        "name": "debug 10",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 960,
        "y": 880,
        "wires": []
    },
    {
        "id": "1931d5485093c185",
        "type": "modbus-flex-getter",
        "z": "b456a9d88b9efc5b",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "logIOActivities": false,
        "server": "4804d9b8eb93f5f9",
        "useIOFile": false,
        "ioFile": "",
        "useIOForPayload": false,
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 370,
        "y": 720,
        "wires": [
            [
                "48d09e589553fd1b"
            ],
            []
        ]
    },
    {
        "id": "1715273a3af8e128",
        "type": "subflow:b5c38da134e475d3",
        "z": "b456a9d88b9efc5b",
        "name": "Utenze meccaniche - 6",
        "env": [
            {
                "name": "ModBusID",
                "value": "6",
                "type": "num"
            }
        ],
        "x": 140,
        "y": 760,
        "wires": [
            [
                "1931d5485093c185"
            ],
            [
                "fd53fc673ff05e45"
            ]
        ]
    },
    {
        "id": "e6dea3ef49527c48",
        "type": "function",
        "z": "b456a9d88b9efc5b",
        "name": "INT32U to INT16",
        "func": "// Funzione per convertire un array [parte alta, parte bassa] in un numero INT32U\nfunction convertToInt32U(array) {\n    // Assicurati che l'array contenga esattamente due elementi\n    if (array.length !== 2) {\n        return null; // Restituisci null se l'array non è valido\n    }\n\n    // Estrai la parte alta e bassa dell'INT32U dall'array\n    var parteAlta = array[0];\n    var parteBassa = array[1];\n\n    // Calcola il numero INT32U\n    var numeroInt32U = (parteAlta * 65536) + parteBassa;\n\n    return numeroInt32U;\n}\n\n// Preleva l'array di input dal payload del nodo precedente\nvar inputArray = msg.payload;\n\n// Chiamata alla funzione di conversione\nvar risultato = convertToInt32U(inputArray);\n\n// Creazione dell'array con il valore convertito\nvar payloadArray = [risultato];\n\n// Creazione del nuovo oggetto di output\nvar outputMsg = {\n    payload: payloadArray,\n    modbusRequest: msg.modbusRequest, // Mantieni l'oggetto modbusRequest originale\n    topic: msg.topic, // Mantieni il topic\n    messageId: msg.messageId, // Mantieni il messageId\n    queueLengthByUnitId: msg.queueLengthByUnitId, // Mantieni queueLengthByUnitId\n    queueUnitId: msg.queueUnitId, // Mantieni queueUnitId\n    unitId: msg.unitId, // Mantieni unitId\n    responseBuffer: msg.responseBuffer, // Mantieni responseBuffer\n    _msgid: msg._msgid // Mantieni _msgid\n};\n\n// Restituisci il messaggio con l'array nel payload e l'ID del messaggio\nreturn outputMsg;\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 370,
        "y": 840,
        "wires": [
            [
                "48d09e589553fd1b"
            ]
        ]
    },
    {
        "id": "fd53fc673ff05e45",
        "type": "modbus-flex-getter",
        "z": "b456a9d88b9efc5b",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "logIOActivities": false,
        "server": "4804d9b8eb93f5f9",
        "useIOFile": false,
        "ioFile": "",
        "useIOForPayload": false,
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 370,
        "y": 780,
        "wires": [
            [
                "e6dea3ef49527c48"
            ],
            []
        ]
    },
    {
        "id": "310e3873c2bcce8e",
        "type": "subflow:b5c38da134e475d3",
        "z": "b456a9d88b9efc5b",
        "name": "Impianto FTV - 5",
        "env": [
            {
                "name": "ModBusID",
                "value": "5",
                "type": "num"
            }
        ],
        "x": 150,
        "y": 1020,
        "wires": [
            [
                "4f81ed714fc95851"
            ],
            [
                "f9e55f69b5e049f7"
            ]
        ]
    },
    {
        "id": "4f81ed714fc95851",
        "type": "modbus-flex-getter",
        "z": "b456a9d88b9efc5b",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "logIOActivities": false,
        "server": "4804d9b8eb93f5f9",
        "useIOFile": false,
        "ioFile": "",
        "useIOForPayload": false,
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 370,
        "y": 980,
        "wires": [
            [
                "07dfbd18275bc6e0"
            ],
            []
        ]
    },
    {
        "id": "07dfbd18275bc6e0",
        "type": "join",
        "z": "b456a9d88b9efc5b",
        "name": "Join - modbusRequest.value",
        "mode": "custom",
        "build": "object",
        "property": "",
        "propertyType": "full",
        "key": "modbusRequest.value",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "13",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 660,
        "y": 1020,
        "wires": [
            [
                "aba2d8e8ca1ecc6b"
            ]
        ]
    },
    {
        "id": "f9e55f69b5e049f7",
        "type": "modbus-flex-getter",
        "z": "b456a9d88b9efc5b",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "showWarnings": true,
        "logIOActivities": false,
        "server": "4804d9b8eb93f5f9",
        "useIOFile": false,
        "ioFile": "",
        "useIOForPayload": false,
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 370,
        "y": 1040,
        "wires": [
            [
                "d80088a92bcf8da4"
            ],
            []
        ]
    },
    {
        "id": "d80088a92bcf8da4",
        "type": "function",
        "z": "b456a9d88b9efc5b",
        "name": "INT32U to INT16",
        "func": "// Funzione per convertire un array [parte alta, parte bassa] in un numero INT32U\nfunction convertToInt32U(array) {\n    // Assicurati che l'array contenga esattamente due elementi\n    if (array.length !== 2) {\n        return null; // Restituisci null se l'array non è valido\n    }\n\n    // Estrai la parte alta e bassa dell'INT32U dall'array\n    var parteAlta = array[0];\n    var parteBassa = array[1];\n\n    // Calcola il numero INT32U\n    var numeroInt32U = (parteAlta * 65536) + parteBassa;\n\n    return numeroInt32U;\n}\n\n// Preleva l'array di input dal payload del nodo precedente\nvar inputArray = msg.payload;\n\n// Chiamata alla funzione di conversione\nvar risultato = convertToInt32U(inputArray);\n\n// Creazione dell'array con il valore convertito\nvar payloadArray = [risultato];\n\n// Creazione del nuovo oggetto di output\nvar outputMsg = {\n    payload: payloadArray,\n    modbusRequest: msg.modbusRequest, // Mantieni l'oggetto modbusRequest originale\n    topic: msg.topic, // Mantieni il topic\n    messageId: msg.messageId, // Mantieni il messageId\n    queueLengthByUnitId: msg.queueLengthByUnitId, // Mantieni queueLengthByUnitId\n    queueUnitId: msg.queueUnitId, // Mantieni queueUnitId\n    unitId: msg.unitId, // Mantieni unitId\n    responseBuffer: msg.responseBuffer, // Mantieni responseBuffer\n    _msgid: msg._msgid // Mantieni _msgid\n};\n\n// Restituisci il messaggio con l'array nel payload e l'ID del messaggio\nreturn outputMsg;\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 370,
        "y": 1100,
        "wires": [
            [
                "07dfbd18275bc6e0"
            ]
        ]
    },
    {
        "id": "aba2d8e8ca1ecc6b",
        "type": "function",
        "z": "b456a9d88b9efc5b",
        "name": "Costruzione JSon (String)",
        "func": "var inputPayload = msg.payload;\nvar sampleEntry = {\n    \"timestamp\": new Date().toISOString().split(\"T\")[0] + \" \" + new Date().toISOString().split(\"T\")[1].split(\".\")[0],\n    \"dev\": String(inputPayload.I1.unitId) // Converte il valore in una stringa\n};\n\nObject.keys(inputPayload).forEach(function (key) {\n    var entry = inputPayload[key];\n\n    if (entry.payload) {\n        // Converti l'array di byte in una stringa\n        var stringValue = entry.payload.join(', ');\n        sampleEntry[entry.modbusRequest.value] = stringValue;\n    } else if (entry.responseBuffer && entry.responseBuffer.data) {\n        // Converti l'array di byte in una stringa\n        var stringValue = entry.responseBuffer.data.join(', ');\n        sampleEntry[entry.modbusRequest.value] = stringValue;\n    }\n});\n\nmsg.payload = {\n    \"key\": inputPayload.I1.topic,\n    \"samples\": [sampleEntry]\n};\n\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 690,
        "y": 880,
        "wires": [
            [
                "0412750b05c06ac6"
            ]
        ]
    },
    {
        "id": "0412750b05c06ac6",
        "type": "json",
        "z": "b456a9d88b9efc5b",
        "name": "",
        "property": "payload",
        "action": "str",
        "pretty": false,
        "x": 850,
        "y": 920,
        "wires": [
            [
                "340ea44d3e221dfe"
            ]
        ]
    },
    {
        "id": "48d09e589553fd1b",
        "type": "join",
        "z": "b456a9d88b9efc5b",
        "name": "Join - modbusRequest.value",
        "mode": "custom",
        "build": "object",
        "property": "",
        "propertyType": "full",
        "key": "modbusRequest.value",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "13",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 660,
        "y": 760,
        "wires": [
            [
                "aba2d8e8ca1ecc6b"
            ]
        ]
    },
    {
        "id": "4804d9b8eb93f5f9",
        "type": "modbus-client",
        "name": "Tosano_Ittico",
        "clienttype": "tcp",
        "bufferCommands": true,
        "stateLogEnabled": false,
        "queueLogEnabled": false,
        "failureLogEnabled": true,
        "tcpHost": "172.20.18.11",
        "tcpPort": "502",
        "tcpType": "DEFAULT",
        "serialPort": "/dev/ttyUSB",
        "serialType": "RTU-BUFFERD",
        "serialBaudrate": "9600",
        "serialDatabits": "8",
        "serialStopbits": "1",
        "serialParity": "none",
        "serialConnectionDelay": "100",
        "serialAsciiResponseStartDelimiter": "0x3A",
        "unit_id": "0",
        "commandDelay": "1",
        "clientTimeout": "1000",
        "reconnectOnTimeout": true,
        "reconnectTimeout": "2000",
        "parallelUnitIdsAllowed": true,
        "showWarnings": true,
        "showLogs": true
    }
]

Can anyone explain to me why?

  1. Because ModBus protocol is a non deterministic protocol
  2. Because you read every single register 1 at a time
    1. This leads to inconsistent data (read on different scans of the PLC/Device)
    2. And multiplies the error margin

A better solution is to request ALL registers in 1 go then parse them all in one go.

NOTE: This uses Buffer-Parser node

The reduces your flows from reading 13 Address x 2 Units (i.e. 26 network requests) - to - 2 larger requests for addresses 12000 ~ 12099 that encompasses your entire range of desired addresses.

NOTE: 1 large request takes marginally (few milliseconds) longer to get than a single request.
e.g.

  • Average Response: 20ms
  • 13 requests: 20*13 === 260ms
  • 26 requests: 20*13 * 2 = 520ms (OVER 1/2 second)
  • 1 large request: ~23ms
  • 2 large request: ~46ms (LESS THAN 1/20th second - AKA 20 times faster)

NOTE: The largest request ModBus can make is 125 WDS (or thereabouts)

DEMO

DEMO FLOW

[{"id":"58d59dcc981c2a91","type":"inject","z":"b7b8756f264f62df","name":"ModBus ID 5","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"ID5","payload":"5","payloadType":"num","x":150,"y":980,"wires":[["d51265445e9f58fb"]]},{"id":"18ca2635ad843891","type":"inject","z":"b7b8756f264f62df","name":"ModBus ID 6","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"ID6","payload":"6","payloadType":"num","x":150,"y":940,"wires":[["d51265445e9f58fb"]]},{"id":"d51265445e9f58fb","type":"link call","z":"b7b8756f264f62df","name":"","links":["720c9e1177d505be"],"linkType":"static","timeout":"10","x":370,"y":960,"wires":[["8a3538751d7c18f6"]]},{"id":"720c9e1177d505be","type":"link in","z":"b7b8756f264f62df","name":"Build MB Request","links":[],"x":285,"y":1040,"wires":[["4ff46a3f6bf84eee"]]},{"id":"6ee022e87bf1ce38","type":"link out","z":"b7b8756f264f62df","name":"link out 1","mode":"return","links":[],"x":815,"y":1040,"wires":[]},{"id":"4ff46a3f6bf84eee","type":"function","z":"b7b8756f264f62df","name":"Build ModBus Req","func":"const ModBusID = msg.payload\nmsg.payload = {\n    'value': 'V12',\n    'fc': 3,\n    'unitid': ModBusID,\n    'address': 12000,\n    'quantity': 100\n}\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":1040,"wires":[["30f46aa7f768dd22"]]},{"id":"0a4198508e456417","type":"comment","z":"b7b8756f264f62df","name":"See INFO panel for mapping","info":"### Mapping\n\nBASE ADDRESS: 12000\nREAD LENGTH: 200\n\nExample:\n* Read from 12000 to 12199\n  * to access 12015, access byte 30\n  * to access 12016, access byte 32\n  * to access 12049, access byte 98\n\n| Address | Byte | Type | Name | Description |\n| ------- | ---- | ---- | ---- | ----------- |\n12015 | 30 | UINT16 | I1 | Corrente I1\n12016 | 32 | UINT16 | I2 | Corrente I2\n12017 | 34 | UINT16 | I3 | Corrente I3\n12029 | 58 | UINT16 | V12 | Concatenata L1 - L2\n12030 | 60 | UINT16 | V23 | Concatenata L2 - L3\n12031 | 62 | UINT16 | V31 | Concatenata L3 - L1\n12040 | 80 | UINT16 | PAT | Potenza Attiva Totale\n12042 | 84 | UINT16 | PRT | Potenza Reattiva Totale\n12044 | 88 | UINT16 | PApT | Potenza Apparente Totale\n12049 | 98 | FLOAT | EAT | Energia Attiva Totale\n12051 | 102 | FLOAT | ERT | Energia Reattiva Totale\n12061 | 122 | FLOAT | EApT | Energia Apparente Totale\n12098 | 196 | UINT16 | FPT | Fattore di Potenza Totale\n","x":400,"y":900,"wires":[]},{"id":"4da7358e52106786","type":"join","z":"b7b8756f264f62df","name":"Join - by topic","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":760,"y":960,"wires":[["38ce3755ecc2b12e"]]},{"id":"30f46aa7f768dd22","type":"function","z":"b7b8756f264f62df","name":"FAKE MODBUS READ","func":"// a 200 UINT16 array of random numbers\nconst fakeData = new Uint16Array(200).map(() => Math.floor(Math.random() * 1000));\nmsg.payload = [...fakeData];\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":660,"y":1040,"wires":[["6ee022e87bf1ce38"]]},{"id":"38ce3755ecc2b12e","type":"debug","z":"b7b8756f264f62df","name":"debug 11","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":930,"y":960,"wires":[]},{"id":"8a3538751d7c18f6","type":"buffer-parser","z":"b7b8756f264f62df","name":"","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"uint16be","name":"I1","offset":30,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"I2","offset":32,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"I3","offset":34,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"V12","offset":58,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"V23","offset":60,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"V31","offset":62,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"PAT","offset":80,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"PRT","offset":84,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"PApT","offset":88,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"EAT","offset":98,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"ERT","offset":102,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"EApT","offset":122,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"FPT","offset":196,"length":1,"offsetbit":0,"scale":"1","mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"return","multipleResult":false,"fanOutMultipleResult":false,"setTopic":true,"outputs":1,"x":570,"y":960,"wires":[["4da7358e52106786","b5537e5a63c465d8"]]},{"id":"b5537e5a63c465d8","type":"debug","z":"b7b8756f264f62df","name":"debug 12","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":740,"y":920,"wires":[]}]

PS: If you replace the "Build Modbus Request" function with a change node - this will be a NO-CODE solution.

PS2: I did not check all details of this demo. For example, in your subflow, you addressed both "Potenza Attiva Totale" and "Potenza Reattiva Totale" to address 12040

Thanks to the immediate response.

Yes, register 12040 is actually wrong, but it's not a problem, I'll solve it right away.

Your flow is much simpler and more functional, the project involves more than monitoring more than two devices and this method seems more effective to me.

I will try later to convert the three Float registers.

Could you help me understand how to setup nodes to allow physical connection to my modbus device?

Furthermore, I understand that it is the "Build ModBus Req" node that decides which register to start from and how many to read, right?

Why is there an offset of 30 instead of 15?

Because a buffer is a byte array. This is called Buffer-Parser, but given an integer array, it auto parse it into a buffer for you. And since ModBus uses 16 bit register, Address 12015 appears in BYTE 30

The reason this is Buffer-Parser and not Array Parser is because ModBus and PLCS and other protocols common denominator is the byte & they ALL mix them up (byte swapped, Little/Big Endian architectures etc etc etc etc). Reducing everything to a byte means we can pretty much handle every oddball data set thrown at it.

Check out the built in help - it explains the fields.

Hi, I went ahead based on your advice but I notice that this solution is also not functional.

I see that only 4 requests come out from the first debug node reading 40 registers per request. I thought the 125 limit was per single request.

That depends on what you have done. Or it could be some devices are finaky and wont play ball. It could be anything - but first - some advice.

Advice

  1. While getting up and running - disable auto repeat of inject nodes and try one at a time
  2. Add a debug node to EVERY node to see what is happening.
  3. Give your debug nodes unique names to make it easier to see what is happening.
  4. When it is all working via manual injects
    1. make 1 inject node with all your devices as a JSON array.
    2. use a split node to create individual (and more importantly) 1-at-a-time messages that flow into the "Build ModBus Req" node
    3. add a delay node set to rate limit mode BEFORE the modbus node to prevent it being swamped - I suggest the rate limit should be something like 2 msg per sec to start with - then fine tune it to get desired reliability

Also, in the debug pane output the amount shown is limited to avoid overloading the browser. I think the output will end in a sequence of dots if it has been truncated.

By creating an Array of this kind, the Flex Getter node does not react

var messages = [
    {
        "fc": 3,
        "unitid": 2,
        "address": 32095,
        "quantity": 40
    },
    {
        "fc": 3,
        "unitid": 3,
        "address": 32095,
        "quantity": 40
    },
    {
        "fc": 3,
        "unitid": 8,
        "address": 32095,
        "quantity": 40
    }
];

return { payload: messages };

No, it wouldnt. Not without a split node to make the array into individual messages.

Put the array into msg.payload then add a split node.

PS also, put a delay node SET TO RATE LIMIT after the split, but before the function.

Basically, everything i said here :point_down:

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