Cloud-Automation / node-modbus

Modbus TCP Client/Server implementation for Node.JS
466 stars 174 forks source link

error on handleErrorPDU() after timeout #146

Closed JasLin closed 7 years ago

JasLin commented 7 years ago

I got an error after the client idle for several minutes, may be modbus device return error PDU, and after that , the client was in error state, and then it can not handle request any more, I have't capture the tcp package yet (I will do that later) . I am think about that should handleErrorPDU try catch unexceptional errors, and made it more robust?

Index out of range","type":"Error","stack":"RangeError: Index out of range\n    
at checkOffset (buffer.js:970:11)\n    
at Buffer.readUInt8 (buffer.js:1008:5)\n    
at handleErrorPDU (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-client-core.js:76:27)\n   
 at Object.<anonymous> (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-client-core.js:117:11)\n   
 at Object.emit (/home/apps/hardware-controller/node_modules/_stampit-event-bus@0.1.1@stampit-event-bus/src/stampit-event-bus.js:20:38)\n    
at Object.<anonymous> (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-tcp-client.js:112:14)\n   
 at emitOne (events.js:115:13)\n    
at Socket.emit (events.js:210:7)\n    
at addChunk (_stream_readable.js:266:12)\n   
 at readableAddChunk (_stream_readable.js:253:11)\n   
 at Socket.Readable.push (_stream_readable.js:211:10)\n    at TCP.onread (net.js:585:20)","v":1}
stefanpoeter commented 7 years ago

Can you give me a code example to reproduce the error.

JasLin commented 7 years ago

@stefanpoeter thanks for reply.

I have found the cause of this issue, the device we got have an custom heat beat (different between tcp keep-alive package). since jsmodbus can not reconginze this custom package, then it close the socket.

2017-09-11 11 21 27

those custom package data is:0xfe

2017-09-11 11 21 31
JasLin commented 7 years ago

so , I am think about that , should we try catch those case(unrecognizable package), and emit an error event instead of close the socket? so , application can handle those nonstandard modbus device by itself.

JasLin commented 7 years ago

more details here:

  1. if we trying to writeCoils after socket closed , it raise ECONNRESET
DEBUG : Trying to flush data.
DEBUG : ready waiting
DEBUG : Sending pdu to the socket.
DEBUG : Data flushed.
ERROR : Socket Error { Error: read ECONNRESET
    at _errnoException (util.js:1041:11)
    at TCP.onread (net.js:606:25) code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
DEBUG : waiting error
ERROR : Client in error state.
DEBUG : Socket closed with error true
DEBUG : error closed
DEBUG : Clearing timeout of the current request.
DEBUG : Cleaning up request fifo.
  1. client auto reconnected to modbus server (the device)
{"pid":13399,"hostname":"cubieboard2","name":"relay-controller","level":20,"time":1505198502611,"msg":"init().onConnect connected to relay server: 192.168.3.233 : 10000","v":1}
  1. modbus server (the device) send an custom heat beat package , and this package lead the Error.
DEBUG : received data
{"pid":13399,"hostname":"cubieboard2","name":"facade","level":50,"time":1505198548092,"msg":"on uncaughtException","v":1}
{"pid":13399,"hostname":"cubieboard2","name":"facade","level":50,"time":1505198548094,"msg":"Index out of range","type":"Error","stack":"RangeError: Index out of range\n    at checkOffset (buffer.js:970:11)\n    at Buffer.readUInt8 (buffer.js:1008:5)\n    at handleErrorPDU (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-client-core.js:76:27)\n    at Object.<anonymous> (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-client-core.js:117:11)\n    at Object.emit (/home/apps/hardware-controller/node_modules/_stampit-event-bus@0.1.1@stampit-event-bus/src/stampit-event-bus.js:20:38)\n    at Object.<anonymous> (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-tcp-client.js:112:14)\n    at emitOne (events.js:115:13)\n    at Socket.emit (events.js:210:7)\n    at addChunk (_stream_readable.js:266:12)\n    at readableAddChunk (_stream_readable.js:253:11)\n    at Socket.Readable.push (_stream_readable.js:211:10)\n    at TCP.onread (net.js:585:20)","v":1}
DEBUG : received data
DEBUG : PDU extracted
DEBUG : received data
{"pid":13399,"hostname":"cubieboard2","name":"facade","level":50,"time":1505198615808,"msg":"on uncaughtException","v":1}
{"pid":13399,"hostname":"cubieboard2","name":"facade","level":50,"time":1505198615809,"msg":"Index out of range","type":"Error","stack":"RangeError: Index out of range\n    at checkOffset (buffer.js:970:11)\n    at Buffer.readUInt8 (buffer.js:1008:5)\n    at handleErrorPDU (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-client-core.js:76:27)\n    at Object.<anonymous> (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-client-core.js:117:11)\n    at Object.emit (/home/apps/hardware-controller/node_modules/_stampit-event-bus@0.1.1@stampit-event-bus/src/stampit-event-bus.js:20:38)\n    at Object.<anonymous> (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-tcp-client.js:112:14)\n    at emitOne (events.js:115:13)\n    at Socket.emit (events.js:210:7)\n    at addChunk (_stream_readable.js:266:12)\n    at readableAddChunk (_stream_readable.js:253:11)\n    at Socket.Readable.push (_stream_readable.js:211:10)\n    at TCP.onread (net.js:585:20)","v":1}
DEBUG : received data
DEBUG : PDU extracted
DEBUG : received data
{"pid":13399,"hostname":"cubieboard2","name":"facade","level":50,"time":1505198680900,"msg":"on uncaughtException","v":1}
{"pid":13399,"hostname":"cubieboard2","name":"facade","level":50,"time":1505198680901,"msg":"Index out of range","type":"Error","stack":"RangeError: Index out of range\n    at checkOffset (buffer.js:970:11)\n    at Buffer.readUInt8 (buffer.js:1008:5)\n    at handleErrorPDU (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-client-core.js:76:27)\n    at Object.<anonymous> (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-client-core.js:117:11)\n    at Object.emit (/home/apps/hardware-controller/node_modules/_stampit-event-bus@0.1.1@stampit-event-bus/src/stampit-event-bus.js:20:38)\n    at Object.<anonymous> (/home/apps/hardware-controller/node_modules/_jsmodbus@2.1.2@jsmodbus/src/modbus-tcp-client.js:112:14)\n    at emitOne (events.js:115:13)\n    at Socket.emit (events.js:210:7)\n    at addChunk (_stream_readable.js:266:12)\n    at readableAddChunk (_stream_readable.js:253:11)\n    at Socket.Readable.push (_stream_readable.js:211:10)\n    at TCP.onread (net.js:585:20)","v":1}
stefanpoeter commented 7 years ago

Thanks for your input. I say that data regarding the transport layer (keep-alive) for example are not supposed to be delivered to the application layer. If this data is transmitted to the application layer and is supposed to be ment for the transportation layer then something underneath is wrong.

When it comes to handling wrong packages I say it is difficult to do. In this case there is not enough data transmitted to cover a whole modbus message, so we have to wait for more data (which won't arrive). If we get wrong data that still fits into a modbus message frame than some error will be shot.

JasLin commented 7 years ago

yes, keep-alive package is not the cause of the error, because it's not delivered to application layer.

I our case , those custom heat beat package from the third-party device lead the error. and it is enough data transmitted, however it's not a standard modbus message. as u see in the screenshot.

stefanpoeter commented 7 years ago

You probably mean a heartbeat package? This is, to my knowledge not part of the modbus specification and shouldn't be handled in this module.

If you want to implement a heartbeat function with modbus then have a look here: http://modbus.control.com/thread/1026158690

JasLin commented 7 years ago

:). yes , heartbeat (sorry for the wrong words heat beat ) , and I knew heartbeat it not port of modbus spec . I mean , I don't want to implements heartbeat in my application. we had bought some modbus devices , those devices implements heartbeat in themselves, and they sent heartbeat package to jsmodbus, those heartbeat packages drive jsmodbus into error. this is exactly what the problem I meet currently . as u can see in the debug log and screenshot.

stefanpoeter commented 7 years ago

You can always create a fork of this project and change it to your needs. Since these heartbeat packages are not part of the modbus specification, changes will not go into the main source.

JasLin commented 7 years ago

ok, I will try to catch those non-modbus package.

thanks for you help.