UNPKG

modbus-browser

Version:

🔦 A Modbus TCP browser application as a command-line client.

116 lines (104 loc) • 4.21 kB
const _ = require('lodash'); const program = require('commander'); const signale = require('signale'); const Chain = require('middleware-chain-js'); const bitwise = require('bitwise'); // Instanciating the middleware chain. const chain = new Chain(); /** * @return a buffer given a list of binary integer * comma delimited list. * @param {*} bits a comma delimited list of binary integers. */ const getBitsBuffer = (bits) => { let array = bits.split(','); if (array.length < 1 || array[0] === '') { throw new Error(`At least one value should be provided.`); } if (array.filter((v) => (v !== '0' && v !== '1') || v === '').length > 0) { throw new Error(`A boolean value is expected for each coil value (e.g '0,1,1,0,0,1').`); } const size = array.length; array = array.map((b) => parseInt(b, 10)); return ([bitwise.buffer.create(array), size]); }; /** * @return a buffer given a list of bytes comma delimited list * @param {*} bytes a comma delimited list of bytes. */ const getBytesBuffer = (bytes) => { let array = bytes.split(','); if (array.length < 1 || array[0] === '') { throw new Error(`At least one value should be provided.`); } array = Buffer.from(array); return ([array, array.length * 8]); }; /** * Command-line interface. */ program .name('modbus-browser write-coils') .description('Writes the given values of multiple coils at the given address.') .option('-s, --server <hostname>', 'The hostname or IP address of the Modbus server to initiate a connection to.') .option('-p, --port <port>', 'The port of the Modbus server to initiate a connection to (set to `502` by default).') .option('-u, --unit-id <unitId>', 'The unit identifier to perform the action on (set to `1` by default).') .option('-a, --start-address <address>', 'The start address at which the given values should be written.') .option('-b, --bits <bits>', 'A comma delimited list of bits to associate with coils to be written (e.g `0,1,0,1,1,0,1,0,0`).') .option('-y, --bytes <bytes>', 'A comma delimited list of bytes to associate with coils to be written (e.g `0xff,0x00,0xfe,0x00`).') .parse(process.argv); /** * Injecting the initialization routines into the `chain`. */ chain.use(require('./lib/middlewares/initialization-routines')); /** * Verifying that the given arguments are valid. */ chain.use((input, output, next) => { if (!_.isString(program.server)) { return (output.fail(`The hostname or IP address of the Modbus server to connect to is expected.`)); } if (!_.isString(program.startAddress)) { return (output.fail(`The address at which the value must be written should be a valid number.`)); } if (_.isString(program.unitId) && isNaN(parseInt(program.unitId, 10))) { return (output.fail(`The unit identifier must be a valid number.`)); } if (!_.isString(program.bits) && !_.isString(program.bytes)) { return (output.fail(`A value to be written at the given address is expected. Provide either a '--bits' or a '--bytes' option.`)); } if (_.isString(program.bits) && _.isString(program.bytes)) { return (output.fail(`Provide either a '--bits' or a '--bytes' option.`)); } const unit = _.isString(program.bits) ? 'bits' : 'bytes'; try { if (unit === 'bits') { // Transforming the given bit values in a buffer. [input.buffer, input.size] = getBitsBuffer(program.bits); } else if (unit === 'bytes') { // Transforming the given byte values in a buffer. [input.buffer, input.size] = getBytesBuffer(program.bytes); } } catch (e) { return (output.fail(e)); } next(); }); /** * Injecting the connection routines into the `chain`. */ chain.use(require('./lib/middlewares/connection-routines')); /** * Reading the coils */ chain.use((input, output) => { const addr = parseInt(program.startAddress, 10); // Writing the value. input.client.writeMultipleCoils(addr, input.buffer, input.size).then(() => { signale.success(`Successfully wrote '${input.buffer.length}' bytes at address '${addr}'.`); // Closing the socket. input.socket.destroy(); }).catch(output.fail); }); // Triggering the `chain`. chain.handle({}, {});