Cloud-Automation / node-modbus

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

onSocketError doesnt emit "error" #31

Closed mainstreetmark closed 8 years ago

mainstreetmark commented 8 years ago

My devices which are offline are not getting the "error" event.

It looks like you need to add this.emit('error') in onSocketError in modbus-tcp-client.js maybe?

stefanpoeter commented 8 years ago

Sorry for the late reply.

I am on it.

stefanpoeter commented 8 years ago

Can you verify?

mainstreetmark commented 8 years ago

Yes, the callback works, though I don't get a numeric code in the results.

code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',

Otherwise, consider it closed. :)

mainstreetmark commented 8 years ago

Actually, that callback may be firing hundreds of times. I log when i try to connect, and I log on('error') and i get lots and lots of errors per connect, within a second. My timeout is set to 1000ms, so every 1000ms, i get a hundred console.logs.

stefanpoeter commented 8 years ago

Can you post some example code.

mainstreetmark commented 8 years ago
var modbus = require('jsmodbus');

// create a modbus client
var client = modbus.client.tcp.complete({
    'host': "10.90.1.199",
    'port': 8888,
    'autoReconnect': true,
    'timeout': 1000,
    'unitId': 0
});

client.connect();

function DoRead() {
    client.readInputRegisters(0, 9).then(function(resp) {
            console.log("input", resp.register);
        })
        .fail("input fail", console.log)
        .done(setTimeout(DoRead, 1000));
    client.readCoils(0, 9).then(function(resp) {
            console.log("coils", resp.coils);
        })
        .fail("coil fail", console.log);
}

client.on('connect', function() {
    DoRead();
});

client.on('error', function(err) {
    console.log("ERROR", err);
});

The ("ERROR", err) line appears hundreds of times the instant I stop the master (which is just running in another terminal window on the same machine)

The master:

var stampit = require('stampit'),
    modbus = require('jsmodbus'),
    _ = require('underscore');

var server = stampit()
    .refs({
        'logEnabled': true,
        'port': 8888,
        'responseDelay': 1
    })
    .compose(modbus.server.tcp.complete)
    .init(function() {

        var init = function() {

            this.on('readHoldingRegistersRequest', function(start, quantity) {
                console.log("HOLDING", 40001 + start, quantity);
                this.getHolding().writeUInt16BE(2, 20); // no work!
                this.getHolding().writeUInt16BE(7, 100);

            });
            this.on('readInputRegistersRequest', function(start, quantity) {
                console.log("INPUTS", 30001 + start, quantity);
                for (var i = start; i < quantity * 2; i += 2)
                    this.getInput().writeUInt16BE(_.random(0, 80), i); // no work!
            });

            this.on('readCoilsRequest', function(start, quantity) {
                console.log("COILS", 10001 + start, quantity);

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

                oldValue = (oldValue + 1) % 255;

                this.getCoils().writeUInt8(oldValue, start);

            });

            this.getCoils().writeUInt8(0, 0);
            this.getCoils().writeUInt8(1, 1);

            this.getInput().writeUInt16BE(42, 0);
            this.getInput().writeUInt16BE(3, 4);
            this.getInput().writeUInt16BE(5, 6);
            this.getInput().writeUInt16BE(5, 8);
            this.getInput().writeUInt16BE(6, 10);
            this.getInput().writeUInt16BE(7, 12);
            this.getInput().writeUInt16BE(8, 14);
            this.getInput().writeUInt16BE(9, 16);

            this.getInput().writeUInt16BE(1, 50);
            this.getInput().writeUInt16BE(4, 52);
            this.getInput().writeUInt16BE(3, 54);
            this.getInput().writeUInt16BE(3, 56);
            this.getInput().writeUInt16BE(5, 58);
            this.getInput().writeUInt16BE(6, 60);
            this.getInput().writeUInt16BE(7, 62);
            this.getInput().writeUInt16BE(8, 64);
            this.getInput().writeUInt16BE(9, 66);

        }.bind(this);

        init();

    });

server();
stefanpoeter commented 8 years ago

The code looks solid.

I just checked: the reconnect mechanism does not use a timeout. The timeout is related to the client requests. So whenever a connection is closed due to a connection loss or an error the reconnect sets in.

Let me check tomorrow if I can quickly use the timeout value for the reconnect or event make it a new setting.