Cloud-Automation / node-modbus

Modbus TCP Client/Server implementation for Node.JS
456 stars 169 forks source link

Struggling to read Input Register (32-bit) #314

Closed dazzlersa closed 1 year ago

dazzlersa commented 1 year ago

Hi Hoping someone can assist. I have been using this lib for a long time, but only for reading Holding Registers, but now I need to read Input Registers (FC-4) and can manage using Simply Modbus TCP Client and it works (returning the voltage of 234v from registers 30001 x 2).

But for the life of me I cannot get the lib to read, constantly get error 11: Modbus Exception. I have tried everything I can think of but always get the same result. Go straight back to Simply Modbus software and it works instantly.

Here is my test code:

`'use strict';

const modbus = require('jsmodbus'); const net = require('net'); const socket = new net.Socket(); const options = { 'host': '10.0.0.90', 'port': '502' };

const client = new modbus.client.TCP(socket, 2); //modbus address 2

socket.on('connect', function () { client.readInputRegisters(30000, 2) .then(({ metrics, request, response }) => { console.log('Transfer Time: ' + metrics.transferTime); console.log('Response Body Payload: ' + response.body.valuesAsArray); console.log('Response Body Payload As Buffer: ' + response.body.valuesAsBuffer); }) .catch(handleErrors) .finally(() => socket.end()); });

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

function handleErrors(err) { if (modbus.errors.isUserRequestError(err)) { console.log('err: ', err); switch (err.err) { case 'OutOfSync': case 'Protocol': case 'Timeout': case 'ManuallyCleared': case 'ModbusException': case 'Offline': case 'crcMismatch': console.log('Error Message: ' + err.message, 'Error' + 'Modbus Error Type: ' + err.err); break; }

} else if (modbus.errors.isInternalException(err)) { console.log('Error Message: ' + err.message, 'Error' + 'Error Name: ' + err.name, err.stack); } else { console.log('Unknown Error', err); } }`

image

What am I missing?

TIA

stefanpoeter commented 1 year ago

Hey @dazzlersa,

you need to loop the readInputRegisters call, a very simple approach would look like this:

const client = new modbus.client.TCP(socket, 2); //modbus address 2

socket.on('connect', () = > {
    const intId = setInterval(() = > {
        client.readInputRegisters(30000, 2).then(({ metrics, request, response }) => {
            console.log('Transfer Time: ' + metrics.transferTime);
            console.log('Response Body Payload: ' + response.body.valuesAsArray);
            console.log('Response Body Payload As Buffer: ' + response.body.valuesAsBuffer);
        }).catch(handleErrors).finally(() => {
            socket.end()
            clearInterval(intId)
        });
    }, 500)
});
dazzlersa commented 1 year ago

Hi @stefanpoeter Thanks for the response. Still getting the same code 11 error:

code:


const modbus = require('jsmodbus');
const net = require('net');
const socket = new net.Socket();
const options = {
  'host': '10.0.0.90',
  'port': '502'
};

const client = new modbus.client.TCP(socket, 2); //modbus address 2

socket.on('connect', () => {
  const intId = setInterval(() => {
    client.readInputRegisters(30000, 2).then(({ metrics, request, response }) => {
      console.log('Transfer Time: ' + metrics.transferTime);
      console.log('Response Body Payload: ' + response.body.valuesAsArray);
      console.log('Response Body Payload As Buffer: ' + response.body.valuesAsBuffer);
    }).catch(handleErrors).finally(() => {
      socket.end();
      clearInterval(intId);
    });
  }, 500);
});

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

function handleErrors(err) {
  if (modbus.errors.isUserRequestError(err)) {
    console.log(`err: `, err);
    switch (err.err) {
      case 'OutOfSync':
      case 'Protocol':
      case 'Timeout':
      case 'ManuallyCleared':
      case 'ModbusException':
      case 'Offline':
      case 'crcMismatch':
        console.log('Error Message: ' + err.message, 'Error' + 'Modbus Error Type: ' + err.err);
        break;
    }

  } else if (modbus.errors.isInternalException(err)) {
    console.log('Error Message: ' + err.message, 'Error' + 'Error Name: ' + err.name, err.stack);
  } else {
    console.log('Unknown Error', err);
  }
}

Result:

modbus-tester % node scratchPad.js
err:  UserRequestError {
  err: 'ModbusException',
  message: 'A Modbus Exception Occurred - See Response Body',
  response: ModbusTCPResponse {
    _id: 1,
    _protocol: 0,
    _bodyLength: 3,
    _unitId: 2,
    _body: ExceptionResponseBody { _fc: 4, _code: 11 }
  }
}
Error Message: A Modbus Exception Occurred - See Response Body ErrorModbus Error Type: ModbusException
err:  UserRequestError {
  err: 'OutOfSync',
  message: 'rejecting because of earlier OutOfSync error',
  response: undefined
}
Error Message: rejecting because of earlier OutOfSync error ErrorModbus Error Type: OutOfSync
err:  UserRequestError {
  err: 'OutOfSync',
  message: 'rejecting because of earlier OutOfSync error',
  response: undefined
}
Error Message: rejecting because of earlier OutOfSync error ErrorModbus Error Type: OutOfSync
err:  UserRequestError {
  err: 'OutOfSync',
  message: 'rejecting because of earlier OutOfSync error',
  response: undefined
}
Error Message: rejecting because of earlier OutOfSync error ErrorModbus Error Type: OutOfSync
err:  UserRequestError {
  err: 'OutOfSync',
  message: 'rejecting because of earlier OutOfSync error',
  response: undefined
}
Error Message: rejecting because of earlier OutOfSync error ErrorModbus Error Type: OutOfSync
err:  UserRequestError {
  err: 'OutOfSync',
  message: 'rejecting because of earlier OutOfSync error',
  response: undefined
}
Error Message: rejecting because of earlier OutOfSync error ErrorModbus Error Type: OutOfSync

Any ideas what else I could try?

stefanpoeter commented 1 year ago

Your device responds with an error code.

 response: ModbusTCPResponse {
    _id: 1,
    _protocol: 0,
    _bodyLength: 3,
    _unitId: 2,
    _body: ExceptionResponseBody { _fc: 4, _code: 11 }
  }

The Modbus Specification states the following:

GATEWAY TARGET FAILED TO RESPOND December 28, 2006 DEVICE Specialized use in conjunction with gateways, indicates that no response was obtained from the target device. Usually means that the device is not present on the network.

dazzlersa commented 1 year ago

Yeah but this is the problem, its giving me that error, but if I use the Simply Modbus TCP software, it gets the correct decoded response every single time.

This is why I am completely stumped. Works on simply modbus TCP software, but not through the library......

Surely I am doing something wrong somewhere...??

stefanpoeter commented 1 year ago

What does wireshark or tcpdump say to this?

dazzlersa commented 1 year ago

tbh haven't used those, lemme see if i can capture some packets.

Kind regards

Darryl Sawyer

On Tue, 30 Aug 2022 at 12:31, Stefan Poeter @.***> wrote:

What does wireshark or tcpdump say to this?

— Reply to this email directly, view it on GitHub https://github.com/Cloud-Automation/node-modbus/issues/314#issuecomment-1231477983, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGZ7TGZIQYR4W6QYZBFSCDV3XPHZANCNFSM575ODNPA . You are receiving this because you were mentioned.Message ID: @.***>