Cloud-Automation / node-modbus

Modbus TCP Client/Server implementation for Node.JS
471 stars 175 forks source link

TCP reading Holding registers. #116

Closed roccomuso closed 7 years ago

roccomuso commented 7 years ago

Here again for another issue..

I'm trying to execute the SimpleServer.js and then doing a ReadHoldingRegister.js 127.0.0.1 8888 5 1

To read the value. Have you tried it? Are these basic tests covered in the Travis CI tests? I'm reading this value:

{ fc: 3, byteCount: 2, payload: <Buffer 00 06>, register: [ 6 ] }

But I'm expecting to see 8. What am I doing wrong now?

stefanpoeter commented 7 years ago

You assume you altered the code from the SimpleServer.js? Post it here then!

roccomuso commented 7 years ago

No, I've not altered the code.. I'm trying this one, on node v4.4.0:

var stampit         = require('stampit'),
    modbus          = require('../..');

var server = stampit()
    .refs({ 
        'logEnabled' : true, 
        'logLevel' : 'debug', 
        'port' : 8888, 
        'responseDelay' : 100,
        'coils'         : new Buffer(100000),
        'holding'       : new Buffer(100000) 
    }).compose(modbus.server.tcp.complete)
    .init(function () {

        var init = function () {

            this.getCoils().writeUInt8(0);

            this.on('readCoilsRequest', function (start, quantity) {

                console.log('readCoilsRequest', start, quantity);

/*                var oldValue = this.getCoils().readUInt8(start);

                oldValue = (oldValue + 1) % 255;

                this.getCoils().writeUInt8(oldValue, start);
*/
            });

            this.on('readHoldingRegistersRequest', function (start, quantity) {

                console.log('readHoldingRegisters', start, quantity);

            });

            this.on('writeSingleCoilRequest', function (adr, value) {

                console.log('writeSingleCoil', adr, value);

            });

            this.getHolding().writeUInt16BE(1, 0); 
            this.getHolding().writeUInt16BE(2, 2); 
            this.getHolding().writeUInt16BE(3, 4); 
            this.getHolding().writeUInt16BE(4, 6); 
            this.getHolding().writeUInt16BE(5, 8); 
            this.getHolding().writeUInt16BE(6, 10); 
            this.getHolding().writeUInt16BE(7, 12); 
            this.getHolding().writeUInt16BE(8, 14); 

        }.bind(this);

        init();

    });

server();
stefanpoeter commented 7 years ago

Could be a error in the example from the readme. The writeUint16BE Method is uint8 aligned so writeUInt16BE(5, 8) is at byte 5 while a call to modbus register 5 is a call to byte 10 and byte 10 is not initiated. Remove the lines containing writeUInt16 methods and replace them with this.getHolding().writeUIn16BE(10, 8). This should work. If so, I'll fix the Readme.

roccomuso commented 7 years ago

At which lines are you referring to? I'm already seeing writeUInt16BE

stefanpoeter commented 7 years ago

Remove this:

            this.getHolding().writeUInt16BE(1, 0); 
            this.getHolding().writeUInt16BE(2, 2); 
            this.getHolding().writeUInt16BE(3, 4); 
            this.getHolding().writeUInt16BE(4, 6); 
            this.getHolding().writeUInt16BE(5, 8); 
            this.getHolding().writeUInt16BE(6, 10); 
            this.getHolding().writeUInt16BE(7, 12); 
            this.getHolding().writeUInt16BE(8, 14); 

and replace it with this:

    this.getHolding().writeUInt16BE(10, 8)
roccomuso commented 7 years ago

Uh, Just now I realized the missing "t". Let me try

roccomuso commented 7 years ago

The writeUIn16BE method doesn't exists....

stefanpoeter commented 7 years ago

That was a typo, I updated the last post. You forgot the "t".

roccomuso commented 7 years ago

@BauchBeinePoe I'm really not understanding.. what's the point of that replacement? You're trying to tell me that a data on the reg. 5 should be written with this.getHolding().writeUInt16BE(10, 8) right?

stefanpoeter commented 7 years ago

node.js Buffer methods are addressing every byte (8bit). So a call to buffer.writeUInt16BE(5, 8) will affect the fifths byte in the buffer (<00 00 00 00 00 00 08>). Since we are writing a 16 bit unsigned integer the 8 is located in byte number six.

Modbus methods are addressing every word (16bit). so a read holding register call to address 5 is actually a read request to byte 10 in the buffer!

That is why, if you want to see the number eight with a read holding register request from address 5, you have to write an unsigned integer with the size of 16bit and the value of 8 to byte 10 in the buffer.

psorowka commented 7 years ago

wait a second here is some confusion!

@BauchBeinePoe buffer.writeUInt16BE(5, 8) writes value 5 to position 8!!

@roccomuso the behavior you observe is totally correct. in the SimpleServer.js, the Holding Registeres are initialized with the this.getHolding().writeUInt16BE lines. This is a node js buffer operation, which has a byte addressing. The line:

this.getHolding().writeUInt16BE(6, 10); 

writes the value 0x0006 to byte position 10/11, which refer to modbus register number 5 (because modbus is addressed as word)

try to illustrate:

| 00 | 01 | 00 | 02 | 00 | 03 | 00 | 04 | 00 | 05 | 00 | 06 | 00 | 07 | <-- value
|  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 | 12 | 13 | <-- byte address
|       0 |       1 |       2 |       3 |       4 |       5 |       6 | <-- modbus address
stefanpoeter commented 7 years ago

Thanks @psorowka, i should really not rely on my memory when citing APIs. And I should probably write more code in node.js. :-)

psorowka commented 7 years ago

If you want to do that in the context of industrial protocols, we should talk about a job :)

roccomuso commented 7 years ago

Now it works.. It was a problem of "inverted" method params as @psorowka underlined