Closed wongjasont closed 6 years ago
I'm writing an implementation of a Modbus Simulator over TCP. I would assume that a "SERVER" would be exactly what I needed for the simulator; so that Modbus Clients would be able to connect to it. The source below creates a Modbus TCP Server. Then creates a client that interacts with it:
'use strict'
let net = require('net');
let modbus = require('jsmodbus');
let netServer = new net.Server()
let server = new modbus.server.TCP(netServer);
let socket = new net.Socket();
let opts = {
host: '127.0.0.1',
port : '5440'
};
let client = new modbus.client.TCP(socket, 1, 30000);
server.on('connection', function (client) {
console.log('connection');
});
server.on('readCoils', function (request, response, send) {
console.log('>>> readCoils', request, response, send);
});
server.on('readInputRegisters', function (request, response, send) {
console.log('>>> readInputRegisters', request, response, send);
});
server.on('readDiscreteInputs', function (request, response, send) {
console.log('>>> readDiscreteInputs', request, response, send);
});
server.on('readHoldingRegisters', function (request, response, send) {
console.log('>>> readHoldingRegisters', request, response, send);
});
server.on('writeSingleRegister', function (value, address) {
console.log('>>> writeSingleRegister', value, address)
});
server.on('writeSingleCoil', function (value) {
console.log('>>> writeMultipleCoils', value)
});
server.on('writeMultipleCoils', function (value) {
console.log('>>> writeMultipleCoils', value)
});
server.on('writeMultipleRegisters', function (value) {
console.log('>>> writeMultipleRegisters')
});
netServer.listen(5440)
function fulfilled(result) {
console.log('RESULT', result.response._body)
}
function rejected(err) {
console.log('ERROR', err)
}
socket.connect(opts);
socket.on('connect', () => {
client.readCoils(1, 1).then(fulfilled, rejected);
client.readInputRegisters(1, 1).then(fulfilled, rejected);
client.readDiscreteInputs(1, 1).then(fulfilled, rejected);
client.readHoldingRegisters(1, 1).then(fulfilled, rejected);
client.writeSingleCoil(1, 1).then(fulfilled, rejected);
client.writeSingleRegister(1, 1).then(fulfilled, rejected);
client.writeMultipleCoils(1, [1], 1).then(fulfilled, rejected);
client.writeMultipleRegisters(1, [1]).then(fulfilled, rejected);
});
I assume that the event listeners listed on the server will all trigger because all methods were called after connect but unfortunately only 2 of them are triggered (writeMultipleCoils, writeMultipleRegisters):
RESULT ReadCoilsResponseBody {...}
RESULT ReadInputRegistersResponseBody {...}
RESULT ReadDiscreteInputsResponseBody {...}
RESULT ReadHoldingRegistersResponseBody {...}
RESULT WriteSingleCoilResponseBody {...}
RESULT WriteSingleRegisterResponseBody {...}
>>> writeMultipleCoils
RESULT WriteMultipleCoilsResponseBody {...}
>>> writeMultipleRegisters
RESULT WriteMultipleRegistersResponseBody {...}
So my question is, how do I get them to trigger those events? I've looked around node-modbus source myself and have only found the emit
calls in tcp-server-response-handler
; is that the only place where these events are emitted? I assume that I will need to implement my own calls like:
server.coils.writeUInt16BE(0x0000, 0)
server.coils.writeUInt16BE(0x0000, 2)
server.coils.writeUInt16BE(0x0000, 4)
server.coils.writeUInt16BE(0x0000, 6)
server.discrete.writeUInt16BE(0x5678, 0)
server.holding.writeUInt16BE(0x0000, 0)
server.holding.writeUInt16BE(0x0000, 2)
server.input.writeUInt16BE(0xff00, 0)
server.input.writeUInt16BE(0xff00, 2)
On every trigger of those events; As seen in /examples/SimpleServer.js
Thank you in advance!
The event,for example writeMultipleCoils, are fired when there is no coils buffer in the server so that you can handle those request with your own buffer or implementation. It is planed that there are pre and post events as you can see here:
this._server.emit('writeMultipleCoils', this._server.coils, oldStatus)
this._server.coils.fill(arrayStatusToBuffer(newStatus))
this._server.emit('postWriteMultipleCoils', this._server.coils, newStatus)
but they are not all implemented. This way you can handle before and after the request execution. Pre and Post handler are implemented for writeMultipleRegisters and writeMultipleCoils.
@stefanpoeter Do you mean that even if the events are not triggered; I can assume that the correct values are returned in response? I have a set of test cases that runs a client against it, writing and reading values but a lot of the test cases are failing:
Test TCP Modbus Mapper
TCP Read and Write boolean
✓ should write true to address 00001
✓ should read true from address 00001
✓ should write false to address 00001
✓ should read false from address 00001
TCP Read and Write string
✓ should write XX to address 40001
✓ should read XX from address 40001
✓ should write XXABCDEF to address 40001
✓ should read XXAB from address 40001
✓ should write XXXX to address 40001
✓ should read XXXX from address 40001
TCP Read and Write uint16
✓ should write 123 to address 40003
1) should read 123 from address 40003
✓ should write 65535 to address 40003
2) should read 65535 from address 40003
✓ should throw error when writing 65536 to address 40003
✓ should throw error when writing -1 to address 40003
TCP Read and Write uint32
✓ should write 123 to address 40004
3) should read 123 from address 40004
✓ should write 4294967295 to address 40004
4) should read 4294967295 from address 40004
✓ should throw error when writing 4294967296 to address 40004
✓ should throw error when writing -1 to address 40004
TCP Read and Write sint16
✓ should write 123 to address 40006
5) should read 123 from address 40006
✓ should write -123 to address 40006
6) should read -123 from address 40006
✓ should write 32767 to address 40006
7) should read 32767 from address 40006
✓ should write -32768 to address 40006
8) should read -32768 from address 40006
✓ should throw error when writing 32768 to address 40006
✓ should throw error when writing -32769 to address 40006
TCP Read and Write sint32
✓ should write 123 to address 40007
9) should read 123 from address 40007
✓ should write -123 to address 40007
10) should read -123 from address 40007
✓ should write 2147483647 to address 40007
11) should read 2147483647 from address 40007
✓ should write -2147483648 to address 40007
12) should read -2147483648 from address 40007
✓ should throw error when writing 2147483648 to address 40007
✓ should throw error when writing -2147483649 to address 40007
TCP Read and Write float32
✓ should write 1.2 to address 40009
13) should read 1.2000000476837158 from address 40009
✓ should write -222.111 to address 40009
14) should read -222.11099243164062 from address 40009
✓ should write 0.0000000000000002 to address 40009
15) should read 2.000000033724767e-16 from address 40009
✓ should write -1.00000000000000001 to address 40009
16) should read -1.00000000000000001 from address 40009
✓ should write 1234567890.123456789 to address 40009
17) should read 1234567936 from address 40009
TCP Read and Write float64
✓ should write 111.222 to address 40011
18) should read 111.222 from address 40011
✓ should write -222.111 to address 40011
19) should read -222.111 from address 40011
✓ should write 0.0000000000000002 to address 40011
20) should read 0.0000000000000002 from address 40011
✓ should write -1.00000000000000001 to address 40011
21) should read -1.00000000000000001 from address 40011
✓ should write 1234567890.123456789 to address 40011
22) should read 1234567890.123456789 from address 40011
TCP Read and Write Whole Mappings
✓ should write all mappings
23) should read all mappings
TCP Test Write Permissions
✓ should throw error when writing true to address 10001
✓ should throw error when writing true to address 19999
✓ should throw error when writing 123 to address 30001
✓ should throw error when writing 123 to address 39999
✓ should throw error when writing 123 to unwritable mapping on address 40001
46 passing (183ms)
23 failing
As you can see, most of the failing tests are either on reading or writing - will still have to investigate. Shockingly, the tests of the high-level type string
are all passing. Initially I used the simulator from https://github.com/dhoomakethu/modbus_sim_cli/tree/master/modbus_sim and all these cases passed, and now I could not point my finger at to where it went wrong.
So does it also mean that the SimpleServer
example is already a master/slave simulator by itself?
So does it also mean that the SimpleServer example is already a master/slave simulator by itself?
Don't know what you mean by simulator but the simple server handles most common modbus functions calls.
Can you redo the test with branch v3.1.0-dev?
@stefanpoeter Test done. The issues are resolved in branch v3.1.0 Thank you for resolving this, I hope the next release will be up soon. Closing this issue now.
Hi,
I'm writing my own Modbus Simulator using node-modbus (My goal is something similar to modbus_sim; https://github.com/dhoomakethu/modbus_sim_cli/tree/master/modbus_sim) I noticed that the example
SimpleServer.js
shows that it is possible.How do I start and which files should I take a close look at?
Many thanks!