Jsmodbus as external javascript in a function node

I know that is node-red-contrib-modbus, but I want to use clear jsmodbus inside node-red.
Inside .node-red folder I install jsmodbus ('npm install -g jsmodbus')
my settings.js

    functionGlobalContext: {
		jsmodbus: require('jsmodbus'),
		net: require('net')
    },

my function

    // create a tcp modbus client
    
let Modbus = global.get('jsmodbus');
let net = global.get('net');
let socket = new net.Socket();
let client = new Modbus.client.TCP(socket);
let options = {
  host: "10.0.0.66",
  port: 502
};

socket.on("connect", function() {
  client
    .readHoldingRegisters(5,1)
    .then(function(resp) {
      msg.m_response = resp.response._body;
      socket.end();
    })
    .catch(function() {
      console.error(
        require("util").inspect(arguments, {
          depth: null
        })
      );
      socket.end();
    });
});


socket.connect(options);

return msg;
[{"id":"6dc680ce450d84b1","type":"tab","label":"jsmodbus","disabled":false,"info":"","env":[]},{"id":"62559f47f6818b55","type":"function","z":"6dc680ce450d84b1","name":"","func":"    // create a tcp modbus client\n    \nlet Modbus = global.get('jsmodbus');\nlet net = global.get('net');\nlet socket = new net.Socket();\nlet client = new Modbus.client.TCP(socket);\nlet options = {\n  host: \"10.0.0.66\",\n  port: 502\n};\n\nsocket.on(\"connect\", function() {\n  client\n    .readHoldingRegisters(5,1)\n    .then(function(resp) {\n      msg.m_response = resp.response._body;\n      socket.end();\n    })\n    .catch(function() {\n      console.error(\n        require(\"util\").inspect(arguments, {\n          depth: null\n        })\n      );\n      socket.end();\n    });\n});\n\n\nsocket.connect(options);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":240,"y":120,"wires":[["abce1ad369e230cc"]]},{"id":"fed32ff3f60dbcfe","type":"inject","z":"6dc680ce450d84b1","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":90,"y":120,"wires":[["62559f47f6818b55"]]},{"id":"abce1ad369e230cc","type":"debug","z":"6dc680ce450d84b1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":420,"y":120,"wires":[]}]

and my error
obraz

Any idea?

The obvious questions first

  • can this instance of node-red ping 10.0.0.66 ?
  • is the device online and is port 502 the correct port?

An end to end test could be performed by using node-red-node-ping (so that the node-red instance from within node env does the pinging)

Yes. I tested by Modbus Pool and its ok.
This error crashed node-red and I must have start node-red again.

That does not verify the node-red instance can contact 10.0.0.66
Please do a ping check from within node-red to the end device.

Also, is node-red running in docker?

Node-red is not from docker.
Ping from node-red is ok.
function from node-red-contrib-modbus give me values.
Problem is with net library I think.

I doubt the net library is a problem (thats node native lib)

if anything the issue is with jsmodbus or your usage.

What is wrong with using node-red-contrib-modbus anyway?

I give from database register address and Ip.
I used ModbusFlexConnector from node-red-contrib-modbus and it's work, but it very slow for many values.

Are you reading values individually or are you reading more than one at a time?

Indyvidually and packages. I have about 20 IP devices and about 100 register for each.

Are the registers spread out or near each other?

The point I am getting to is...

  • If (for example) you request MB registers 11, 13, 15, 44, 66, 68, 69, 70, 80, 88, 101 ~ 130, 150~189 as 12 reads - that is much more expensive than requesting 2 reads of 10~99 and 100~189

Yes, but sometimes is situation that 11,13 but register 12 doesn't exist.
I must have refresh time 1-5 second for all points. If I have many
obraz block it's ok, but with that
obraz I must use delay.
I have something like this


It's not all.
I have table when I set value to devices by modbus. Before I used php, but now, I try to move to node-red :slight_smile:

Do you mean that if the device does not have a register 12 that the communication fails?

To be more precise...
If you requested 3 registers starting from register 11 even though you don't need register 12, does the modbus communication work or does it fail?

Fail, or I waiting as timeout finish. I can't use it.
Is not situation that I don't need 12 register. It give me '0' or something.
I tested that situation.

In pure js I write this and it works in node.js

const Modbus = require('jsmodbus')
const net = require('net')
const socket = new net.Socket()
const client = new Modbus.client.TCP(socket, 1)
const options = {
'host' : '10.0.0.66',
'port' : 502
}

//const client = new modbus.client.TCP(socket)

socket.on('connect', function () {
  client.readHoldingRegisters(8737, 4)
    .then(function (resp) {
      console.log(resp.response._body.valuesAsArray)
      socket.end()
    }).catch(function () {
      console.error(require('util').inspect(arguments, {
        depth: null
      }))
      socket.end()
    })
})

socket.on('error', console.error)
socket.connect(options)

Ok understand.

Can you share your flow and some sample data (capture the payload from your database debug node & paste it into an inject node) so I can simulate your issue.

I think I know your issue with the contrib node.

If that doesn't work, I'll help you get the function node working.

Sample with ModbusFlexConnector

[{"id":"ca6d31db8909b2f6","type":"inject","z":"13b11b04.342725","name":"","repeat":"3600","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":130,"y":1220,"wires":[["ec442f7307e32a81","acac9bff0a533975"]]},{"id":"ec442f7307e32a81","type":"function","z":"13b11b04.342725","name":"","func":"var table1 = msg.c1;\nvar query = \"SELECT delta, nazwa, host, modbus_id from temp_tid where delta>0\";\nmsg.topic = query;\nreturn msg;","outputs":1,"noerr":0,"x":300,"y":1220,"wires":[["36ac1d98a418f21c"]]},{"id":"36ac1d98a418f21c","type":"mysql","z":"13b11b04.342725","mydb":"36c886e2.421612","name":"db","x":430,"y":1220,"wires":[["ebe864bd81c84cc5"]]},{"id":"ebe864bd81c84cc5","type":"debug","z":"13b11b04.342725","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":600,"y":1220,"wires":[]},{"id":"931f37b035f53f14","type":"modbus-flex-connector","z":"13b11b04.342725","name":"","maxReconnectsPerMinute":4,"emptyQueue":false,"showStatusActivities":true,"showErrors":false,"server":"5cac7a09.32364c","x":630,"y":1320,"wires":[["bb18a1e21ba1d629"]]},{"id":"c4ae37ebd438db19","type":"modbus-flex-sequencer","z":"13b11b04.342725","name":"sequencer 1","sequences":[{"name":"1","unitid":"1","fc":"FC4","address":"10009","quantity":"1"}],"server":"5cac7a09.32364c","showStatusActivities":true,"showErrors":true,"logIOActivities":false,"useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":1010,"y":1320,"wires":[["bc2bc1764d1916c2","e12b723b657d0bcb"],[]]},{"id":"bc2bc1764d1916c2","type":"debug","z":"13b11b04.342725","name":"output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1170,"y":1320,"wires":[]},{"id":"bb18a1e21ba1d629","type":"delay","z":"13b11b04.342725","name":"","pauseType":"delay","timeout":"9","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"outputs":1,"x":840,"y":1320,"wires":[["c4ae37ebd438db19"]]},{"id":"52b1389934190985","type":"function","z":"13b11b04.342725","name":"f1","func":"var devices1 =[{\"delta\":1,\"nazwa\":\"ED_9373\",\"host\":\"10.0.0.202\",\"modbus_id\":8},{\"delta\":2,\"nazwa\":\"ED_9376\",\"host\":\"10.0.0.132\",\"modbus_id\":2},{\"delta\":3,\"nazwa\":\"ED_9377\",\"host\":\"10.0.0.201\",\"modbus_id\":4},{\"delta\":4,\"nazwa\":\"ED_9375\",\"host\":\"10.0.0.203\",\"modbus_id\":9},{\"delta\":5,\"nazwa\":\"ED_9379\",\"host\":\"10.0.0.204\",\"modbus_id\":5},{\"delta\":6,\"nazwa\":\"ED_9374\",\"host\":\"10.0.0.203\",\"modbus_id\":3},{\"delta\":8,\"nazwa\":\"ED_9380\",\"host\":\"10.0.0.202\",\"modbus_id\":7},{\"delta\":9,\"nazwa\":\"ED_9381\",\"host\":\"10.0.0.203\",\"modbus_id\":6},{\"delta\":7,\"nazwa\":\"ED_9378\",\"host\":\"10.0.0.131\",\"modbus_id\":10}];\nvar devices = msg.payload;\n\n\ndevices.forEach(dev => {\n\n   node.send({\n      \"topic\": dev.nazwa,\n      \"payload\": {\n         \"connectorType\" : \"TCP\",\n         \"tcpHost\": dev.host,\n         \"tcpPort\": \"502\",\n         \"unitId\": dev.modbus_id\n      },\n      \"sequences\": [\n    {\n        name: dev.host,\n        unitid: dev.modbus_id,\n        fc: 4,\n        address: 10009,\n        quantity: 1\n    }\n    ]\n   });\n\n})\n\n\n\nreturn null;","outputs":1,"noerr":0,"x":230,"y":1320,"wires":[["589fdf93fe8d790d","297df7472b57f343"]]},{"id":"589fdf93fe8d790d","type":"debug","z":"13b11b04.342725","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":410,"y":1360,"wires":[]},{"id":"297df7472b57f343","type":"delay","z":"13b11b04.342725","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"10","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"outputs":1,"x":400,"y":1320,"wires":[["931f37b035f53f14"]]},{"id":"e12b723b657d0bcb","type":"function","z":"13b11b04.342725","name":"","func":"var table = 'alarmy';\nvar bat = msg.payload[0];\nvar modbus_id = msg.unitId;\nvar query = '';\n\n\nquery= `UPDATE temp_tid set bat = ${bat} WHERE modbus_id= ${modbus_id};`;\n\n\nmsg.query = query;\nmsg.topic = query;\n\n\nreturn msg;\n\n\n\n\n","outputs":1,"noerr":0,"x":1020,"y":1400,"wires":[["9cba012d79a7d3e1"]]},{"id":"9cba012d79a7d3e1","type":"mysql","z":"13b11b04.342725","mydb":"36c886e2.421612","name":"db","x":1150,"y":1400,"wires":[[]]},{"id":"59dd46656ff38922","type":"comment","z":"13b11b04.342725","name":"json","info":"[{\"delta\":1,\"nazwa\":\"ED_9373\",\"host\":\"192.168.98.201\",\"modbus_id\":8},{\"delta\":2,\"nazwa\":\"ED_9376\",\"host\":\"192.168.98.203\",\"modbus_id\":2},{\"delta\":3,\"nazwa\":\"ED_9377\",\"host\":\"192.168.98.202\",\"modbus_id\":4},{\"delta\":4,\"nazwa\":\"ED_9375\",\"host\":\"192.168.98.203\",\"modbus_id\":9},{\"delta\":5,\"nazwa\":\"ED_9379\",\"host\":\"192.168.98.204\",\"modbus_id\":5},{\"delta\":6,\"nazwa\":\"ED_9374\",\"host\":\"192.168.98.203\",\"modbus_id\":4},{\"delta\":8,\"nazwa\":\"ED_9380\",\"host\":\"192.168.98.202\",\"modbus_id\":7},{\"delta\":9,\"nazwa\":\"ED_9381\",\"host\":\"192.168.1.132\",\"modbus_id\":6},{\"delta\":7,\"nazwa\":\"ED_9378\",\"host\":\"10.0.0.1\",\"modbus_id\":10}]","x":770,"y":1220,"wires":[]},{"id":"acac9bff0a533975","type":"function","z":"13b11b04.342725","name":"","func":"msg.payload = [{\"delta\":1,\"nazwa\":\"ED_9373\",\"host\":\"192.168.98.201\",\"modbus_id\":8},{\"delta\":2,\"nazwa\":\"ED_9376\",\"host\":\"192.168.98.203\",\"modbus_id\":2},{\"delta\":3,\"nazwa\":\"ED_9377\",\"host\":\"192.168.98.202\",\"modbus_id\":4},{\"delta\":4,\"nazwa\":\"ED_9375\",\"host\":\"192.168.98.203\",\"modbus_id\":9},{\"delta\":5,\"nazwa\":\"ED_9379\",\"host\":\"192.168.98.204\",\"modbus_id\":5},{\"delta\":6,\"nazwa\":\"ED_9374\",\"host\":\"192.168.98.203\",\"modbus_id\":4},{\"delta\":8,\"nazwa\":\"ED_9380\",\"host\":\"192.168.98.202\",\"modbus_id\":7},{\"delta\":9,\"nazwa\":\"ED_9381\",\"host\":\"192.168.1.132\",\"modbus_id\":6},{\"delta\":7,\"nazwa\":\"ED_9378\",\"host\":\"10.0.0.1\",\"modbus_id\":10}];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":100,"y":1320,"wires":[["52b1389934190985"]]},{"id":"36c886e2.421612","type":"MySQLdatabase","name":"","host":"localhost","port":"3306","db":"chema","tz":"","charset":"UTF8"},{"id":"5cac7a09.32364c","type":"modbus-client","name":"","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"tcpHost":"192.168.98.203","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","unit_id":"0","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":false,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true}]

Sample with Modbus Read

[{"id":"7eef272d35972c7e","type":"modbus-read","z":"6dc680ce450d84b1","name":"","topic":"","showStatusActivities":true,"logIOActivities":false,"showErrors":true,"unitid":"","dataType":"HoldingRegister","adr":"8637","quantity":"100","rate":"1","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"81dd93cb.5ed208","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":true,"x":450,"y":360,"wires":[["5b58d539eec7b040"],[]]},{"id":"5b58d539eec7b040","type":"debug","z":"6dc680ce450d84b1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":640,"y":360,"wires":[]},{"id":"81dd93cb.5ed208","type":"modbus-client","name":"10.0.0.151","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"tcpHost":"10.0.0.151","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"","unit_id":"1","commandDelay":"1","clientTimeout":"10000","reconnectOnTimeout":true,"reconnectTimeout":"20000","parallelUnitIdsAllowed":true}]

If some register not exist's I have error
obraz

On that example, you are asking for 100 REG from 8637 (8637 ~ 8736) - is it not a case of going above some internal memory max location?

Or is it definitely some random unavailable address(es) inside that range?

On that example, you are asking for 100 REG from 8637 (8637 ~ 8736) - is it not a case of going above some internal memory max location?

No, I tested 4 000 register (0-99, 100-199...4000) and it was OK. Refresh time 5 sec from PLC.

Or is it definitely some random unavailable address(es) inside that range?

Yes. Some devices has separately range like 0-10 20-30 and address 11 will give unavailable error.

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