UNPKG

nodebots-interchange

Version:

Tool to build custom backpack firmwares to make devices I2C compliant

153 lines (130 loc) 4.02 kB
const events = require('events'); const parsers = require('serialport').parsers; // used for parser const SerialPort = require('serialport'); const ReadLine = require('@serialport/parser-readline'); const util = require('util'); const NL = 0x0a; function Client() { let port_address = null; const sp_open = false; // const sp_timeout = null; let current_state = null; let current_callback = null; const state_write = (data) => { // just passes the data up to anything that wants to listen for it. this.emit('data', data); // clear any callbacks current_callback = null; }; const state_init = (data) => { // initialising the connection, waits for the magic chars to come out if (data.indexOf('>>') >=0) { // now we move to just writing anything from the serial line out. current_state = state_write; this.emit('ready'); } }; const state_dump = (data) => { // waits for the state dump to come back and then parses the json and // current_state = state_write; let dump; try { dump = JSON.parse(data); } catch (err) { if (current_callback != null) { current_callback(err); } } if (current_callback != null) { current_callback(null, dump); } }; current_state = state_init; this.serialport = null; this.get_info = (cb) => { this.serialport.write('DUMP\n'); current_state = state_dump; current_callback = cb; }; this.set_details = async(data, cb) => { // sets the details of the firmware onto the device current_state = state_write; await new Promise((resolve, reject) => { this.serialport.write('CLR\n'); resolve('CLR'); }).then(() => { const s = 'FID ' + data.firmwareID + '\n'; this.serialport.write(s); return ('FID'); }).then(() => { this.serialport.write('CID ' + data.creatorID + '\n'); return 'CID'; }).then(() => { this.serialport.write('I2C ' + data.i2c_address + ' ' + data.use_custom_address + '\n'); return 'I2C'; }).then(async() => { // give the serialport time to finish executing before you close out await setTimeout(() => {}, 20); cb(); }).catch(err => { throw err; }); }; this.close = () => { if (this.open) { this.serialport.close(); } }; Object.defineProperties(this, { 'open': { get() { // gives back whether the serialport is open or not let open = false if (this.serialport) { open = this.serialport.isOpen; } return open; } }, 'port': { set(p) { if (p != undefined) { // set up the port here. const parser = new ReadLine(); const opts = {baudRate: 9600}; this.serialport = new SerialPort(p, opts, (err) => { if (err) { this.emit('error', err); } }); this.serialport.pipe(parser); // create handlers for the various serial port actions. this.serialport.on('open', () => { // once connection is open, emit that but then this will do nothing // further. After data comes back in from the SP then the data will // flow through the parser data event instead. port_address = p; this.emit('connected'); }); // These are catch all scenarios to surface an error in a low level // library. No need for explicit tests. /* istanbul ignore next */ this.serialport.on('error', (err) => { this.emit('error', err); }); /* istanbul ignore next */ parser.on('error', (err) => { this.emit('error', err); }); parser.on('data', (data) => current_state(data)); } }, get() { return port_address; } } }); } util.inherits(Client, events.EventEmitter); module.exports.Client = Client;