Closed ekawahyu closed 6 years ago
connection
and listener
must be top level properties. If not present, defaults (tcp) are used.
Correct:
const master = modbus.createMaster({
transport: transport,
connection: connection
});
Wrong:
const master = modbus.createMaster({
transport: {
connection: connection
}
});
Ok, I have updated the snippets above, but I got the same error still. Thanks for the prompt reply!
Apparently, I need to execute slave.js
with sudo
. Now the master can get connected to the slave, but I still got these error on the slave:
sudo node slave.js
listener#open
listener#client: 1
client#1#error: TypeError: Cannot read property 'fromBuffer' of undefined
at ApplicationDataUnit.toRequest (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/ApplicationDataUnit.js:66:49)
at Slave.handleAdu (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/Slave.js:213:21)
at emitOne (events.js:115:13)
at RemoteClient.emit (events.js:210:7)
at IpTransportState.handleCompleteFrame (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/transports/IpTransport.js:381:13)
at IpTransportState.handleIncompleteFrame (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/transports/IpTransport.js:353:12)
at IpTransportState.onData (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/transports/IpTransport.js:309:10)
at emitOne (events.js:115:13)
at RemoteClient.emit (events.js:210:7)
at Socket.readable (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/listeners/TcpListener.js:266:18)
rps=0 (min=0 max=0 cur=0) req=0 res=0 err=0 rss=27 (min=27 max=27)
rps=0 (min=0 max=0 cur=0) req=0 res=0 err=0 rss=27 (min=27 max=27)
client#1#close
And these are the error on the master:
node master.js
Connected!
No response was received from the slave in the specified time.
No response was received from the slave in the specified time.
Error suggests usage of an unsupported function code (or a broken frame).
Add some more logging:
slave.listener.on('client', client =>
{
console.log('listener#client');
client.on('error', err => console.log('client#error: %s', err.stack));
client.on('close', () => console.log('client#close'));
client.on('data', data => console.log('client#data:', data));
client.on('write', data => console.log('client#write:', data));
});
The part that I don't understand... is that why would the slave need sudo permission? I granted access to peripherals like serial port, so somewhere in the code still requires access to the networking stuff? How to disable it and let it run RTU transport only over the serial port.
BTW, I added the logging per your suggestion, the error messages look the same.
If the serial slave is properly configured and used then the default TCP shouldn't start. Check netstat
and/or try to write a simple client/server with only node-serialport (using the same config options and without sudo).
BTW, I added the logging per your suggestion, the error messages look the same.
I need the full client/server code & output (especially client#data: ...
).
I have tested node-serialport only and it works without requiring sudo. I have physically wired two computers with USB to Serial/RS485 adapter and node-serialport perfectly works, no sudo required. When I look at the h5.modbus code, setting up its transport layer to RTU and connection type as serial are the only thing to configure. But there is something with the listener that invokes something requiring sudo. What else I can configure in the listener?
SerialListener
has the following options:
serialPort
an instance of node-serialport.serialPortOptions
- if serialPort
isn't specified, this will be used to create a new instance.autoOpen
- bool - whether to automatically call the listener.open()
function.closeOnDestroy
- bool - whether to call serialPort.close()
on listener.destroy()
(one might not want the external serialPort
to be closed along with the listener).suppressErrorsAfterDestroy
- bool - whether a dummy function should be added to the serial port instance as an error
event listener to catch any potiential errors that might crash the process.If you look at the source there is nothing special that would require sudo (include node-serialport, instantiate it and call open()).
I think the more I look into the source code, the more I found the deprecated code for the serial port. For example, SerialPort.SerialPort
is deprecated, isOpen()
has now become a property instead of function. I got more error after fixing the source here and there. I believe the node-serialport code are not up-to-date:
https://github.com/node-serialport/node-serialport/blob/master/UPGRADE_GUIDE.md
Yup, when the SerialListener
was written, node-serialport
was at version 2 (now 6).
Ok, I updated some lines to match the latest node-serialport API. But now I am stuck on this:
node master.js
/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/Master.js:489
connection.on('open', this.onConnectionOpen);
^
TypeError: connection.on is not a function
at Master.setUpConnection (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/Master.js:489:16)
at new Master (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/Master.js:51:28)
at Object.<anonymous> (/Users/nodino/Downloads/conectric-wi/js/master.js:8:16)
at Module._compile (module.js:624:30)
at Object.Module._extensions..js (module.js:635:10)
at Module.load (module.js:545:32)
at tryModuleLoad (module.js:508:12)
at Function.Module._load (module.js:500:3)
at Function.Module.runMain (module.js:665:10)
at startup (bootstrap_node.js:187:16)
What am I missing here? the Master
is an extends of EventEmitter
, yet it says that .on
is not one of its methods?
It says the connection doesn't have the .on()
, but Connection
is also EventEmitter
so the connection passed to the master is not an instance of Connection
.
Show me how you are creating the master+connection+transport.
var SerialPort = require('serialport');
var modbus = require('h5.modbus');
var serial = new SerialPort('/dev/tty.virtual1', {
baudRate: 9600
});
var master = new modbus.Master({
transport: {
type: 'rtu',
eofTimeout: 10, // End of frame timeout
},
connection: {
type: 'serial',
serialPort: serial
}
});
When instantiating Master
directly you also have to directly pass instances of Transport
and Connection
.
Options objects with type
property are only accepted in the createMaster()
factory function (which in turn uses createTransport()
and createConnection()
).
So either:
var master = modbus.createMaster({
transport: {
type: 'rtu',
eofTimeout: 10, // End of frame timeout
},
connection: {
type: 'serial',
serialPort: serial
}
});
or
var connection = new modbus.SerialConnection({serialPort});
var transport = new modbus.RtuTransport({eofTimeout: 10});
var master = new modbus.Master({connection, transport});
Ok, that fixed the issue. Now, moving on to the slave.js:
var SerialPort = require('serialport');
var modbus = require('h5.modbus');
var serial = new SerialPort('/dev/tty.virtual0', {
baudRate: 9600
});
var slave = modbus.createSlave({
requestHandler: handleRequest,
transport: {
type: 'rtu',
eofTimeout: 10, // End of frame timeout
},
listener: {
type: 'serial',
serialPort: serial
}
});
function handleRequest(unit, request, respond)
{
respond(modbus.ExceptionCode.IllegalFunctionCode);
}
slave.listener.on('client', client =>
{
console.log('listener#client');
client.on('error', err => console.log('client#error: %s', err.stack));
client.on('close', () => console.log('client#close'));
client.on('data', data => console.log('client#data:', data));
client.on('write', data => console.log('client#write:', data));
});
This is the error it throws:
node slave.js
events.js:182
throw er; // Unhandled 'error' event
^
Error: Port is opening
at SerialPort.open (/Users/nodino/Downloads/conectric-wi/node_modules/serialport/lib/serialport.js:231:29)
at SerialListener.open (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/listeners/SerialListener.js:144:21)
at new SerialListener (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/listeners/SerialListener.js:94:12)
at createByType (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/index.js:312:7)
at Object.exports.createListener (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/index.js:246:10)
at Object.exports.createSlave (/Users/nodino/Downloads/conectric-wi/node_modules/h5.modbus/lib/index.js:204:30)
at Object.<anonymous> (/Users/nodino/Downloads/conectric-wi/js/slave.js:8:20)
at Module._compile (module.js:624:30)
at Object.Module._extensions..js (module.js:635:10)
at Module.load (module.js:545:32)
I don't have any process holding up the serial port, nor other slave process running. How to solve this issue?
var serial = new SerialPort('/dev/tty.virtual0', {
baudRate: 9600,
autoOpen: false
});
Ok, that works! At least I don't need to run sudo
for the slave and the master is able to send something over the serial port and received by the slave.
The fixed I did on the serialport
is as follow:
SerialListerner.js and SerialConnection.js:
isOpen()
{
//return this.serialPort !== null && this.serialPort.isOpen();
return this.serialPort !== null && this.serialPort.isOpen;
}
setUpSerialPort(serialPort)
{
if (!serialPort)
{
if (SerialPort === null)
{
//SerialPort = require('serialport').SerialPort;
SerialPort = require('serialport');
}
//
...
//
}
AFK, will continue working tomorrow, thanks a lot! I think you can close this issue.
I am trying to write the code to talk Modbus RTU over the serial port with no success. I posted an issue here since I could not find any documentation somehow? Here are my master.js and slave.js code and the errors I got:
master.js:
slave.js:
These are the error I got on master:
These are the error I got on slave:
Why would it try to create a local server if all it needs to do is to get connected through RS485 devices. What did I do wrong? Thank you.