avrgirl-arduino = function (opts) {
opts = opts || {};
this.options = {
debug: opts.debug || false,
board: opts.board || 'uno',
port: opts.port || ''
};
// this here checks for 3 conditions:
// if debug option is simply true, we want to fall back to default debug function
// if a custom debug function is passed in, we want to assign debug to be that
// if debug option is false, then run debug as a no-op
if (this.options.debug === true) {
this.debug = console.log.bind(console);
} else if (typeof this.options.debug === 'function') {
this.debug = this.options.debug;
} else {
this.debug = function() {};
}
if (typeof this.options.board === 'string') {
this.options.board = boards.byName[this.options.board];
} else if (typeof this.options.board === 'object') {
this.options.board = this.options.board;
}
this.connection = new Connection(this.options);
if (this.options.board) {
var Protocol = protocols[this.options.board.protocol] || function() {};
this.protocol = new Protocol({
board: this.options.board,
connection: this.connection,
debug: this.debug
});
}
}n/a
avr109 = function (options) {
options.protocol = function() { return AVR109; };
Protocol.call(this, options);
}n/a
connection = function (options) {
this.options = options;
this.debug = this.options.debug ? console.log.bind(console) : function() {};
this.board = this.options.board;
}n/a
list = function (callback) {
return Connection.prototype._listPorts(callback);
}...
port: '/dev/cu.usbmodem1412'
});
```
You can list available USB ports programmatically using the the `list` method:
```javascript
Avrgirl.list(function(err, ports) {
console.log(ports);
/*
[ { comName: '/dev/cu.usbmodem1421',
manufacturer: 'Arduino (www.arduino.cc)',
serialNumber: '55432333038351F03170',
pnpId: '',
locationId: '0x14200000',
...listPorts = function (callback) {
return Connection.prototype._listPorts(callback);
}...
case 'boards': {
var boardNames = Object.keys(boards.byName).sort();
console.log('Supported Boards:\n - ' + boardNames.join('\n - '));
break;
}
case 'list': {
Avrgirl.listPorts(function(err, ports) {
console.log(ports);
});
break;
}
case 'help': {
...protocol = function (options) {
this.debug = options.debug;
this.board = options.board;
this.connection = options.connection;
this.chip = new options.protocol({ quiet: true });
}...
*/
var Protocol = function(options) {
this.debug = options.debug;
this.board = options.board;
this.connection = options.connection;
this.chip = new options.protocol({ quiet: true });
};
/**
* Resets an Arduino STK500 bootloaded chip by pulsing DTR high.
*
* Avoids the dreaded timeout bug if the serialport was opened since the device
* was powered.
...stk500v1 = function (options) {
options.protocol = STK;
Protocol.call(this, options);
}n/a
stk500v2 = function (options) {
options.protocol = function() { return STK2; };
Protocol.call(this, options);
}n/a
avr109 = function (options) {
options.protocol = function() { return AVR109; };
Protocol.call(this, options);
}n/a
super_ = function (options) {
this.debug = options.debug;
this.board = options.board;
this.connection = options.connection;
this.chip = new options.protocol({ quiet: true });
}n/a
_reset = function (callback) {
var _this = this;
var conn;
// creating a temporary connection for resetting only
var tempSerialPort = new Serialport(_this.connection.options.port, {
baudRate: 1200,
autoOpen: false
});
_this.connection.serialPort = tempSerialPort;
conn = _this.connection;
_this.debug('resetting board...');
_this.connection.serialPort.once('close', function() {
async.series([
conn._setUpSerial.bind(conn),
conn._pollForPort.bind(conn)
],
function(error) {
return callback(error);
});
});
async.series([
tempSerialPort.open.bind(tempSerialPort),
conn._cycleDTR.bind(conn)
],
function(error) {
if (error) {
return callback(error);
}
});
}...
} else {
data = file;
}
} catch (error) {
return callback(error);
}
_this._reset(function(error) {
if (error) { return callback(error); }
_this.debug('reset complete.');
_this.connection._pollForOpen(function(error) {
if (error) { return callback(error); }
..._upload = function (file, callback) {
var _this = this;
var data;
try {
if (typeof file === 'string') {
data = fs.readFileSync(file, {
encoding: 'utf8'
});
} else {
data = file;
}
} catch (error) {
return callback(error);
}
_this._reset(function(error) {
if (error) { return callback(error); }
_this.debug('reset complete.');
_this.connection._pollForOpen(function(error) {
if (error) { return callback(error); }
_this.debug('connected');
_this._write(data, function(error) {
var color = (error ? colors.red : colors.green);
_this.debug(color('flash complete.'));
// Can't close the serialport on avr109 boards >> node-serialport/issues/415
// _this.serialPort.close();
return callback(error);
});
});
});
}...
if (error) { return callback(error); }
// set up serialport connection
_this.connection._init(function(error) {
if (error) { return callback(error); }
// upload file to board
_this.protocol._upload(file, callback);
});
});
};
/**
* Return a list of devices on serial ports. In addition to the output provided
* by SerialPort.list, it adds a platform independent PID in _pid
..._write = function (data, callback) {
var _this = this;
var options = {
signature: _this.board.signature.toString(),
debug: false
};
_this.chip.init(_this.connection.serialPort, options, function(error, flasher) {
if (error) { return callback(error); }
_this.debug('flashing, please wait...');
async.series([
flasher.erase.bind(flasher),
flasher.program.bind(flasher, data.toString()),
function verify(done) {
flasher.verify(done);
},
flasher.fuseCheck.bind(flasher)
],
function(error) {
return callback(error);
});
});
}...
_this.debug('reset complete.');
_this.connection._pollForOpen(function(error) {
if (error) { return callback(error); }
_this.debug('connected');
_this._write(data, function(error) {
var color = (error ? colors.red : colors.green);
_this.debug(color('flash complete.'));
// Can't close the serialport on avr109 boards >> node-serialport/issues/415
// _this.serialPort.close();
return callback(error);
...connection = function (options) {
this.options = options;
this.debug = this.options.debug ? console.log.bind(console) : function() {};
this.board = this.options.board;
}n/a
_cycleDTR = function (callback) {
var _this = this;
async.series([
_this._setDTR.bind(_this, true, 250),
_this._setDTR.bind(_this, false, 50)
],
function(error) {
return callback(error);
});
}...
*
* @param {function} callback - function to run upon completion/error
*/
Protocol.prototype._reset = function(callback) {
var _this = this;
// cycle DTR/RTS from low to high
_this.connection._cycleDTR(function(error) {
if (!error) {
_this.debug('reset complete.');
}
return callback(error);
});
};
..._init = function (callback) {
var _this = this;
// check for port
if (!_this.options.port) {
// no port, auto sniff for the correct one
_this._sniffPort(function(error, port) {
if (port.length) {
// found a port, save it
_this.options.port = port[0].comName;
_this.debug('found ' + _this.options.board.name + ' on port ' + _this.options.port);
// set up serialport for it
_this._setUpSerial(function(error) {
return callback(error);
});
} else {
// we didn't find the board
return callback(new Error('no Arduino ' + '\'' + _this.options.board.name + '\'' + ' found.'));
}
});
} else {
// when a port is manually specified
_this._setUpSerial(function(error) {
return callback(error);
});
}
}...
var _this = this;
// validate board properties first
_this._validateBoard(function(error) {
if (error) { return callback(error); }
// set up serialport connection
_this.connection._init(function(error) {
if (error) { return callback(error); }
// upload file to board
_this.protocol._upload(file, callback);
});
});
};
..._listPorts = function (callback) {
var foundPorts = [];
// list all available ports
Serialport.list(function(err, ports) {
if (err) { return callback(err); }
// iterate through ports
for (var i = 0; i < ports.length; i += 1) {
var pid;
// are we on windows or unix?
if (ports[i].productId) {
pid = ports[i].productId;
} else if (ports[i].pnpId) {
try {
pid = '0x' + /PID_\d*/.exec(ports[i].pnpId)[0].substr(4);
} catch (err) {
pid = '';
}
} else {
pid = '';
}
ports[i]._standardPid = pid;
foundPorts.push(ports[i]);
}
return callback(null, foundPorts);
});
}...
* Return a list of devices on serial ports. In addition to the output provided
* by SerialPort.list, it adds a platform independent PID in _pid
*
* @param {function} callback - function to run upon completion/error
*/
AvrgirlArduino.prototype.listPorts = AvrgirlArduino.listPorts =
AvrgirlArduino.prototype.list = AvrgirlArduino.list = function(callback) {
return Connection.prototype._listPorts(callback);
};
module.exports = AvrgirlArduino;
..._pollForOpen = function (callback) {
var _this = this;
var poll = awty(function(next) {
_this.serialPort.open(function(error) {
next(!error);
});
});
poll.every(100).ask(6);
poll(function(isOpen) {
var error;
if (!isOpen) {
error = new Error('could not open board on ' + _this.serialPort.path);
}
callback(error);
});
}...
}
_this._reset(function(error) {
if (error) { return callback(error); }
_this.debug('reset complete.');
_this.connection._pollForOpen(function(error) {
if (error) { return callback(error); }
_this.debug('connected');
_this._write(data, function(error) {
var color = (error ? colors.red : colors.green);
_this.debug(color('flash complete.'));
..._pollForPort = function (callback) {
var _this = this;
var poll = awty(function(next) {
var found = false;
// try to sniff port instead (for port hopping devices)
_this._sniffPort(function(error, port) {
if (port.length) {
// found a port, save it
_this.options.port = port[0].comName;
found = true;
}
next(found);
});
});
poll.every(100).ask(15);
poll(function(foundPort) {
if (foundPort) {
// set up serialport for it
_this._setUpSerial(function(error) {
return callback(error);
});
} else {
// we also could not find the device on auto sniff
return callback(new Error('could not reconnect after resetting board.'));
}
});
}n/a
_setDTR = function (bool, timeout, callback) {
var _this = this;
var props = {
rts: bool,
dtr: bool
};
_this.serialPort.set(props, function(error) {
if (error) { return callback(error); }
setTimeout(function() {
callback(error);
}, timeout);
});
}...
});
});
};
Stk500v1.prototype._reset = function(callback) {
var _this = this;
_this.connection._setDTR(true, 250, function(error) {
if (!error) {
_this.debug('reset complete.');
}
return callback(error);
});
};
..._setUpSerial = function (callback) {
this.serialPort = new Serialport(this.options.port, {
baudRate: this.board.baud,
autoOpen: false
});
return callback(null);
}...
if (port.length) {
// found a port, save it
_this.options.port = port[0].comName;
_this.debug('found ' + _this.options.board.name + ' on port ' + _this.options.port);
// set up serialport for it
_this._setUpSerial(function(error) {
return callback(error);
});
} else {
// we didn't find the board
return callback(new Error('no Arduino ' + '\'' + _this.options.board.name + '\'' +
x27; found.'));
}
});
..._sniffPort = function (callback) {
var _this = this;
var pidList = _this.board.productId.map(function(id) {
return parseInt(id, 16);
});
_this._listPorts(function(error, ports) {
// filter for a match by product id
var portMatch = ports.filter(function(p) {
return pidList.indexOf(parseInt(p._standardPid, 16)) !== -1;
});
return callback(null, portMatch);
});
}...
Connection.prototype._init = function(callback) {
var _this = this;
// check for port
if (!_this.options.port) {
// no port, auto sniff for the correct one
_this._sniffPort(function(error, port) {
if (port.length) {
// found a port, save it
_this.options.port = port[0].comName;
_this.debug('found ' + _this.options.board.name + ' on port ' + _this.options.port);
// set up serialport for it
...protocol = function (options) {
this.debug = options.debug;
this.board = options.board;
this.connection = options.connection;
this.chip = new options.protocol({ quiet: true });
}...
*/
var Protocol = function(options) {
this.debug = options.debug;
this.board = options.board;
this.connection = options.connection;
this.chip = new options.protocol({ quiet: true });
};
/**
* Resets an Arduino STK500 bootloaded chip by pulsing DTR high.
*
* Avoids the dreaded timeout bug if the serialport was opened since the device
* was powered.
..._reset = function (callback) {
var _this = this;
// cycle DTR/RTS from low to high
_this.connection._cycleDTR(function(error) {
if (!error) {
_this.debug('reset complete.');
}
return callback(error);
});
}...
} else {
data = file;
}
} catch (error) {
return callback(error);
}
_this._reset(function(error) {
if (error) { return callback(error); }
_this.debug('reset complete.');
_this.connection._pollForOpen(function(error) {
if (error) { return callback(error); }
...avr109 = function (options) {
options.protocol = function() { return AVR109; };
Protocol.call(this, options);
}n/a
stk500v1 = function (options) {
options.protocol = STK;
Protocol.call(this, options);
}n/a
stk500v2 = function (options) {
options.protocol = function() { return STK2; };
Protocol.call(this, options);
}n/a
stk500v1 = function (options) {
options.protocol = STK;
Protocol.call(this, options);
}n/a
super_ = function (options) {
this.debug = options.debug;
this.board = options.board;
this.connection = options.connection;
this.chip = new options.protocol({ quiet: true });
}n/a
_reset = function (callback) {
var _this = this;
_this.connection._setDTR(true, 250, function(error) {
if (!error) {
_this.debug('reset complete.');
}
return callback(error);
});
}...
} else {
data = file;
}
} catch (error) {
return callback(error);
}
_this._reset(function(error) {
if (error) { return callback(error); }
_this.debug('reset complete.');
_this.connection._pollForOpen(function(error) {
if (error) { return callback(error); }
..._upload = function (file, callback) {
var _this = this;
this.serialPort = this.connection.serialPort;
// open/parse supplied hex file
var hex = tools._parseHex(file);
if (!Buffer.isBuffer(hex)) {
return callback(hex);
}
// open connection
_this.serialPort.open(function(error) {
if (error) { return callback(error); }
_this.debug('connected');
// reset
_this._reset(function(error) {
if (error) { return callback(error); }
_this.debug('flashing, please wait...');
// flash
_this.chip.bootload(_this.serialPort, hex, _this.board, function(error) {
var color = (error ? colors.red : colors.green);
_this.debug(color('flash complete.'));
// Always close the serialport
_this.serialPort.close();
return callback(error);
});
});
});
}...
if (error) { return callback(error); }
// set up serialport connection
_this.connection._init(function(error) {
if (error) { return callback(error); }
// upload file to board
_this.protocol._upload(file, callback);
});
});
};
/**
* Return a list of devices on serial ports. In addition to the output provided
* by SerialPort.list, it adds a platform independent PID in _pid
...stk500v2 = function (options) {
options.protocol = function() { return STK2; };
Protocol.call(this, options);
}n/a
super_ = function (options) {
this.debug = options.debug;
this.board = options.board;
this.connection = options.connection;
this.chip = new options.protocol({ quiet: true });
}n/a
_upload = function (file, callback) {
var _this = this;
// open/parse supplied hex file
_this.serialPort = _this.connection.serialPort;
var hex = tools._parseHex(file);
if (!Buffer.isBuffer(hex)) {
return callback(hex);
}
// open connection
_this.serialPort.open(function(error) {
if (error) { return callback(error); }
_this.debug('connected');
// instantiate stk500v2 with newly open serialport
var chip = _this.chip(_this.serialPort);
async.series([
_this._reset.bind(_this),
chip.sync.bind(chip, 5),
chip.verifySignature.bind(chip, _this.board.signature),
chip.enterProgrammingMode.bind(chip, _this.board),
function debugLog(callback) {
_this.debug('flashing, please wait...');
callback(null);
},
chip.upload.bind(chip, hex, _this.board.pageSize),
chip.exitProgrammingMode.bind(chip)
],
function(error) {
var color = (error ? colors.red : colors.green);
_this.debug(color('flash complete.'));
// Always close the serialport
_this.serialPort.close();
return callback(error);
});
});
}...
if (error) { return callback(error); }
// set up serialport connection
_this.connection._init(function(error) {
if (error) { return callback(error); }
// upload file to board
_this.protocol._upload(file, callback);
});
});
};
/**
* Return a list of devices on serial ports. In addition to the output provided
* by SerialPort.list, it adds a platform independent PID in _pid
..._parseHex = function (file) {
try {
var data;
if (typeof file === 'string') {
data = fs.readFileSync(file, {
encoding: 'utf8'
});
} else {
data = file;
}
return intelhex.parse(data).data;
} catch (error) {
return error;
}
}...
*/
Stk500v1.prototype._upload = function(file, callback) {
var _this = this;
this.serialPort = this.connection.serialPort;
// open/parse supplied hex file
var hex = tools._parseHex(file);
if (!Buffer.isBuffer(hex)) {
return callback(hex);
}
// open connection
_this.serialPort.open(function(error) {
if (error) { return callback(error); }
...