wifirm
Version:
Upload new firmware onto Boards with WiFiMCU-Compatible bootloaders.
134 lines (103 loc) • 4.08 kB
JavaScript
const pkg = require(__dirname + '/package.json');
const prog = require('commander');
const lightYModem = require('particle-ymodem');
const SerialPort = require('serialport').SerialPort;
const fs = require('fs');
const async = require('async');
const progressbar = require('progressbar');
const defaultBaudrate = 115200;
const highestBaudrate = 230400;
var port = null;
prog
.version(pkg.version)
.option('-D, --device <path>','Specify the serial port to use')
.option('-b, --baudrate <baud> [optional]','Set a specific baudrate (Default: ' + defaultBaudrate + ')')
.option('-f, --file <path>','Binary firmware file to upload')
.parse(process.argv);
var argError = function (error) { console.error("Error:", error); };
// Check arguments and initialize everything
async.waterfall([
// Check if specified file exists and can be read
function fileArgCheck (callback) {
if (prog.file === undefined)
return callback("No file to upload was specified");
fs.access(prog.file, fs.R_OK, function (err) {
if (err)
return callback("The file \"" + prog.file + "\" can't be read. " +
"Please make sure that it exists and you have the right permissions.");
else return callback(null);
});
},
// Check if baudrate is supplied and a valid int, else throw error or set default
function baudrateArgCheck (callback) {
if (!prog.baudrate) prog.baudrate = defaultBaudrate;
else if (prog.baudrate > 0 && prog.baudrate <= highestBaudrate)
prog.baudrate = parseInt(prog.baudrate);
else
return callback("The specified baudrate is invalid");
return callback(null);
},
// Check if device-argument and open serial port
function deviceArgCheck (callback) {
if (prog.device === undefined)
return callback("No serial port was specified.");
// Open serial port (check existance and access)
port = new SerialPort(prog.device, {baudrate: prog.baudrate}, false);
port.open(function (err) {
if (err)
return callback("Can't open the serial port: " + err.message);
else {
console.log("Serial Port opened! -> Using \"" + prog.device
+ "\" with baudrate", prog.baudrate);
return callback();
}
});
},
// Check if device is in Bootloader and then enter upload mode
function bootloaderCheck (callback) {
console.log("Waiting for WiFiMCU to enter Bootloader");
var bootloaderCheck = function () {
port.write('help\n');
}
var checkInterval = setInterval(bootloaderCheck, 5000);
bootloaderCheck();
var inBootloader = false;
var dataRecvFunc = function (data) {
if (!inBootloader) {
//console.log("Data: " + data);
if (data.indexOf("WiFiMCU Bootloader") > -1) {
inBootloader = true;
// We are in the bootloader!!!
console.log("In bootloader-mode, entering upload mode");
// Stop the "help" commands and don't call this method anymore
clearInterval(checkInterval);
dataRecvFunc = function () {return;};
setTimeout(function () {
port.write('1\n');
setTimeout(callback, 500);
}, 500);
}}
}
port.on('data', dataRecvFunc);
},
// Upload file now
function uploadFile (callback) {
var logCallback = console.log;
var modem = new lightYModem();
var file = fs.readFileSync(prog.file);
fs.writeFileSync("/tmp/fileout", file);
console.log("Reopening serial port.");
port.close();
port = new SerialPort(prog.device, {baudrate: prog.baudrate}, false);
console.log("Initiating upload...");
var progress = progressbar.create().step('upload').setTotal(1000);
var progressCallback = function(val){ progress.setTick(Math.round(val.current/val.total * 1000));}
var serialLog = "";
modem.transfer(file, port, progressCallback,
(data) => { serialLog += data; },
() => { console.log("Serial port closed, exiting..."); process.exit(0); });
}
], function (error) {
if(error) argError(error);
});