node-modbus / stream

NodeJS Modbus Stream
MIT License
174 stars 52 forks source link

Cannot set property 'code' of null #1

Closed robogeek closed 7 years ago

robogeek commented 7 years ago

I have a USB RS485 adapter connected to a MODBUS temperature sensor. I have a C program using libmodbus successfully reading the device. I want to use Node.js, of course.

I'm getting this error:

$ sudo node mstemp.js 
<< automaton-123 0x[ 01, 04, 00, 01, 00, 01, 60, 0A ]
>> automaton-123 0x[ 01, 04, 02, 0C ]
events.js:160
      throw er; // Unhandled 'error' event
      ^

TypeError: Cannot set property 'code' of null
    at Object.exports.Response (/home/david/modbus-server/node_modules/modbus-pdu/lib/Modbus.js:84:16)
    at SerialPort.<anonymous> (/home/david/modbus-server/node_modules/modbus-stream/lib/transport/transport.js:82:24)
    at emitOne (events.js:96:13)
    at SerialPort.emit (events.js:188:7)
    at SerialPort.raw (/home/david/modbus-server/node_modules/serialport/lib/parsers.js:7:13)
    at SerialPort._emitData (/home/david/modbus-server/node_modules/serialport/lib/serialport.js:313:18)
    at SerialPort.<anonymous> (/home/david/modbus-server/node_modules/serialport/lib/serialport.js:293:14)
    at SerialPort.<anonymous> (/home/david/modbus-server/node_modules/serialport/lib/serialport.js:306:7)
    at FSReqWrap.wrapper [as oncomplete] (fs.js:681:17)

The line of code is here in modbus-pdu:

 if (typeof exports[k] == "object" && exports[k].Code == code) {
                                var data = exports[k].Response.parse(buffer);

                                if (typeof data == "object" && !util.isArray(data)) {
                                        data.code = k;  // CRASH HERE
                                } else {
                                        data = { code: k, data: data };
                                }

                                return data;
                        }

So.. going by the crash, somehow data is null but by the test it has typeof == object and it is not an array.

My code is adapted from your examples:

const modbus = require('modbus-stream');
const util   = require('util');

modbus.serial.connect("/dev/ttyUSB0", {
    // except "debug", everything else is the default for serial
    baudRate : 9600,
    dataBits : 8,
    stopBits : 1,
    parity   : "none",
    debug    : "automaton-123"
}, (err, connection) => {
    if (err) throw err;

    connection.readInputRegisters({ address: 1, quantity: 1 }, (err, res) => {
        if (err) throw err;

        console.log(res); // response
    })
});

Something I see missing -- not setting the device ID to connect to. The device is at ID=1 and I see in the protocol dump that is the address which was requested.

robogeek commented 7 years ago

I changed typeof data == "object" to typeof data === "object" and now get this:

$ sudo node mstemp.js 
<< automaton-123 0x[ 01, 04, 00, 01, 00, 01, 60, 0A ]
>> automaton-123 0x[ 01, 04, 02, 0C, 0F, FC, 34 ]
{ slaveId: 1,
  crc: 13564,
  expected_crc: 13564,
  pdu: <Buffer 04 02 0c 0f>,
  callback: [Function],
  response: { code: 'ReadInputRegisters', data: [ <Buffer 0c 0f> ] } }

This looks like a successful query -- I just need to do a bit of work to decode the value.

The same issue, using == instead of ===, exists in both the Request and Response functions.

dresende commented 7 years ago

There's something missing there. It seems you might have replied in a way the module is not expecting. Do you have a complete example? Also, try the latest version as I fixed some bugs lately.

dresende commented 7 years ago

I changed typeof data == "object" to typeof data === "object" and now get this:

This shouldn't be the reason you now get a valid response.

In your initial comment you had this:

>> automaton-123 0x[ 01, 04, 02, 0C ]

Which is an incomplete response. In your last comment you have the complete one:

>> automaton-123 0x[ 01, 04, 02, 0C, 0F, FC, 34 ]

Your data is there (0x0C, 0x0F), you can also see it in the object your printed. If that's a complete register and it is (u)int16 big endian, that would be 3087 (or 308,7 or 30,87 or .... if it's not in engineering units). You can read this data using the common Buffer methods.

dresende commented 7 years ago

Please reopen if you find any problems.