Search code examples
javascriptnode.jstcp

Node.js TCP write multiple commands


I am connecting to a serial device over the internet, using an ethernet to serial device. I am communicating with it via a small node.js app. The following code gets back the information I need:

var net = require('net');

var zone1 = 'AgABBgAJ';
var zone2 = 'AgACBgAK';
var zone3 = 'AgACBfAZ';
var zone4 = 'AgACBaAW';
var zone5 = 'AgACBsAV';

var client = new net.Socket();
client.connect(10006, '10.0.1.217', function() {
    console.log('Connected');
    client.write(Buffer.from(zone1, 'base64').toString('ascii')+'\n');

});

client.on('data', function(data) {
    var data_array = new Uint8Array(data);
    console.log(data_array);
    var decoded = [];
    decoded['zone'] = data_array[16];
    decoded['power'] = data_array[18] == 128 ? 'On' : data_array[18] == 0 ? 'Off' : data_array[18] == 192 ? 'Muted' : 'Unknown';
    decoded['input'] = data_array[22] + 1;
    decoded['vol'] = data_array[23] - 196;
    decoded['mute'] = data_array[18] == 192 ? 'On' : 'Off';
    decoded['state'] = (data_array[18] == 128) || (data_array[18] == 192) ? true : false;

    console.log('-- Zone: ' + decoded['zone']);
    console.log('-- Power: ' + decoded['power']);
    console.log('-- Input: ' + decoded['input']);
    console.log('-- Volume: ' + decoded['vol']);
    console.log('-- Mute: ' + decoded['mute']);

    client.destroy(); // kill client after server's response
});

client.on('close', function() {
    console.log('Connection closed');
});

What I need to do now is write the other commands (zone2,zone3,zone4,zone5) and get the data back from them as well.

Is there a way to loop through an array of commands and output the data after each command?

Thanks!

EDIT: Here is the output from the app

Connected
Uint8Array [
  2, 0, 0,   6, 0, 63, 0,   0,
  0, 0, 0,   0, 0, 71, 2,   0,
  1, 5, 0,   0, 0,  0, 0, 222,
  8, 8, 0, 246
]
-- Zone: 1
-- Power: Off
-- Input: 1
-- Volume: 26
-- Mute: Off
Connection closed

Solution

  • You can create yourself a little state machine where you put the zones in an array and keep a variable that points to the next index in that array to process. Then, after you finish processing the data event for a zone, you send the command for the next zone until you have no more items in the array.

    const net = require('net');
    
    const zones = [
        'AgABBgAJ',
        'AgACBgAK',
        'AgACBfAZ',
        'AgACBaAW',
        'AgACBsAV'
    ];
    
    let zoneIndex = 0;
    const client = new net.Socket();
    
    function sendNextZone() {
        if (zoneIndex < zones.length) {
            client.write(Buffer.from(zones[zoneIndex++], 'base64').toString('ascii')+'\n');
        } else {
            // no more zones to send,  so we're done
            client.destroy();
        }
    }
    
    
    client.connect(10006, '10.0.1.217', function() {
        console.log('Connected');
        sendNextZone();    
    });
    
    client.on('data', function(data) {
        let data_array = new Uint8Array(data);
        console.log(data_array);
        let decoded = [];
        decoded['zone'] = data_array[16];
        decoded['power'] = data_array[18] == 128 ? 'On' : data_array[18] == 0 ? 'Off' : data_array[18] == 192 ? 'Muted' : 'Unknown';
        decoded['input'] = data_array[22] + 1;
        decoded['vol'] = data_array[23] - 196;
        decoded['mute'] = data_array[18] == 192 ? 'On' : 'Off';
        decoded['state'] = (data_array[18] == 128) || (data_array[18] == 192) ? true : false;
    
        console.log('-- Zone: ' + decoded['zone']);
        console.log('-- Power: ' + decoded['power']);
        console.log('-- Input: ' + decoded['input']);
        console.log('-- Volume: ' + decoded['vol']);
        console.log('-- Mute: ' + decoded['mute']);
    
        // done processing this zone, send the command for the next one
        sendNextZone();
    });
    
    client.on('close', function() {
        console.log('Connection closed');
    });
    
    client.on('error', function(err) {
        console.log(err);
    });
    

    Note: There is no complete guarantee with a TCP socket that you will get all the data you want in one data event - it is possible, particularly with larger data sets or slower networks that the data might be split between multiple data events. If that were the case, you would need a buffer so you could buffer data until you had a "full" set of data that you could then process.