Skip to content

Commit

Permalink
Removed duplication in node.js apps with 2 new libraries, added an 'a…
Browse files Browse the repository at this point in the history
…pp test' program - not finished yet
  • Loading branch information
gfwilliams committed Dec 16, 2022
1 parent cf59aac commit b89a368
Show file tree
Hide file tree
Showing 7 changed files with 392 additions and 230 deletions.
42 changes: 7 additions & 35 deletions bin/apploader.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ for Noble.
var SETTINGS = {
pretokenise : true
};
var APPSDIR = __dirname+"/../apps/";
var noble;
["@abandonware/noble", "noble"].forEach(module => {
if (!noble) try {
Expand All @@ -37,36 +36,18 @@ function ERROR(msg) {
process.exit(1);
}

//eval(require("fs").readFileSync(__dirname+"../core/js/utils.js"));
var AppInfo = require("../core/js/appinfo.js");
global.Const = {
/* Are we only putting a single app on a device? If so
apps should all be saved as .bootcde and we write info
about the current app into app.info */
SINGLE_APP_ONLY : false,
};
var deviceId = "BANGLEJS2";
var apps = [];
var dirs = require("fs").readdirSync(APPSDIR, {withFileTypes: true});
dirs.forEach(dir => {
var appsFile;
if (dir.name.startsWith("_example") || !dir.isDirectory())
return;
try {
appsFile = require("fs").readFileSync(APPSDIR+dir.name+"/metadata.json").toString();
} catch (e) {
ERROR(dir.name+"/metadata.json does not exist");
return;
}
apps.push(JSON.parse(appsFile));
});

var apploader = require("./lib/apploader.js");
var args = process.argv;

var bangleParam = args.findIndex(arg => /-b\d/.test(arg));
if (bangleParam!==-1) {
deviceId = "BANGLEJS"+args.splice(bangleParam, 1)[0][2];
}
apploader.init({
DEVICEID : deviceId
});
if (args.length==3 && args[2]=="list") cmdListApps();
else if (args.length==3 && args[2]=="devices") cmdListDevices();
else if (args.length==4 && args[2]=="install") cmdInstallApp(args[3]);
Expand All @@ -90,7 +71,7 @@ process.exit(0);
}

function cmdListApps() {
console.log(apps.map(a=>a.id).join("\n"));
console.log(apploader.apps.map(a=>a.id).join("\n"));
}
function cmdListDevices() {
var foundDevices = [];
Expand All @@ -113,19 +94,10 @@ function cmdListDevices() {
}

function cmdInstallApp(appId, deviceAddress) {
var app = apps.find(a=>a.id==appId);
var app = apploader.apps.find(a=>a.id==appId);
if (!app) ERROR(`App ${JSON.stringify(appId)} not found`);
if (app.custom) ERROR(`App ${JSON.stringify(appId)} requires HTML customisation`);
return AppInfo.getFiles(app, {
fileGetter:function(url) {
console.log(__dirname+"/"+url);
return Promise.resolve(require("fs").readFileSync(__dirname+"/../"+url).toString("binary"));
},
settings : SETTINGS,
device : { id : deviceId }
}).then(files => {
//console.log(files);
var command = files.map(f=>f.cmd).join("\n")+"\n";
return apploader.getAppFilesString(app).then(command => {
bangleSend(command, deviceAddress).then(() => process.exit(0));
});
}
Expand Down
59 changes: 9 additions & 50 deletions bin/firmwaremaker.js
Original file line number Diff line number Diff line change
@@ -1,71 +1,30 @@
#!/usr/bin/env nodejs
#!/usr/bin/env node
/*
Mashes together a bunch of different apps to make
a single firmware JS file which can be uploaded.
*/
var SETTINGS = {
pretokenise : true
};

var path = require('path');
var ROOTDIR = path.join(__dirname, '..');
var APPDIR = ROOTDIR+'/apps';
var OUTFILE = ROOTDIR+'/firmware.js';
var DEVICE = "BANGLEJS";
var DEVICEID = "BANGLEJS";
var APPS = [ // IDs of apps to install
"boot","launch","mclock","setting",
"about","alarm","widbat","widbt","welcome"
];
var MINIFY = true;

var fs = require("fs");
global.Const = {
/* Are we only putting a single app on a device? If so
apps should all be saved as .bootcde and we write info
about the current app into app.info */
SINGLE_APP_ONLY : false,
};
var apploader = require("./lib/apploader.js");
apploader.init({
DEVICEID : DEVICEID
});

var AppInfo = require(ROOTDIR+"/core/js/appinfo.js");
var appfiles = [];

function fileGetter(url) {
console.log("Loading "+url)
if (MINIFY) {
/*if (url.endsWith(".js")) {
var f = url.slice(0,-3);
console.log("MINIFYING "+f);
const execSync = require('child_process').execSync;
// --config PRETOKENISE=true
// --minify
code = execSync(`espruino --config SET_TIME_ON_WRITE=false --minify --board BANGLEJS ${f}.js -o ${f}.min.js`);
console.log(code.toString());
url = f+".min.js";
}*/
if (url.endsWith(".json")) {
var f = url.slice(0,-5);
console.log("MINIFYING JSON "+f);
var j = eval("("+fs.readFileSync(url).toString("binary")+")");
var code = JSON.stringify(j);
//console.log(code);
url = f+".min.json";
fs.writeFileSync(url, code);
}
}
return Promise.resolve(fs.readFileSync(url).toString("binary"));
}

Promise.all(APPS.map(appid => {
try {
var app = JSON.parse(fs.readFileSync(APPDIR + "/" + appid + "/metadata.json").toString());
} catch (e) {
throw new Error(`App ${appid} not found`);
}
return AppInfo.getFiles(app, {
fileGetter : fileGetter,
settings : SETTINGS,
device : { id : DEVICE }
}).then(files => {
var app = apploader.apps.find(a => a.id==appid);
if (!app) throw new Error(`App ${appid} not found`);
return apploader.getAppFiles(app).then(files => {
appfiles = appfiles.concat(files);
});
})).then(() => {
Expand Down
63 changes: 12 additions & 51 deletions bin/firmwaremaker_c.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,20 @@ to populate Storage initially.
Bangle.js 1 doesn't really have anough flash space for this,
but we have enough on v2.
*/
var SETTINGS = {
pretokenise : true
};

var DEVICE = process.argv[2];
var DEVICEID = process.argv[2];

var path = require('path');
var fs = require("fs");
var ROOTDIR = path.join(__dirname, '..');
var APPDIR = ROOTDIR+'/apps';
var MINIFY = true;
var OUTFILE, APPS;

if (DEVICE=="BANGLEJS") {
if (DEVICEID=="BANGLEJS") {
var OUTFILE = path.join(ROOTDIR, '../Espruino/libs/banglejs/banglejs1_storage_default.c');
var APPS = [ // IDs of apps to install
"boot","launch","mclock","setting",
"about","alarm","sched","widbat","widbt","welcome"
];
} else if (DEVICE=="BANGLEJS2") {
} else if (DEVICEID=="BANGLEJS2") {
var OUTFILE = path.join(ROOTDIR, '../Espruino/libs/banglejs/banglejs2_storage_default.c');
var APPS = [ // IDs of apps to install
"boot","launch","antonclk","setting",
Expand All @@ -37,16 +32,12 @@ if (DEVICE=="BANGLEJS") {
console.log(" bin/firmwaremaker_c.js BANGLEJS2");
process.exit(1);
}
console.log("Device = ",DEVICE);

console.log("Device = ",DEVICEID);

var fs = require("fs");
global.Const = {
/* Are we only putting a single app on a device? If so
apps should all be saved as .bootcde and we write info
about the current app into app.info */
SINGLE_APP_ONLY : false,
};
var apploader = require("./lib/apploader.js");
apploader.init({
DEVICEID : DEVICEID
});


function atob(input) {
Expand Down Expand Up @@ -84,31 +75,8 @@ function atob(input) {
return new Uint8Array(output);
}

var AppInfo = require(ROOTDIR+"/core/js/appinfo.js");
var appfiles = [];

function fileGetter(url) {
console.log("Loading "+url)
if (MINIFY) {
if (url.endsWith(".json")) {
var f = url.slice(0,-5);
console.log("MINIFYING JSON "+f);
var j = eval("("+fs.readFileSync(url).toString("binary")+")");
var code = JSON.stringify(j);
//console.log(code);
url = f+".min.json";
fs.writeFileSync(url, code);
}
}
var blob = fs.readFileSync(url);
var data;
if (url.endsWith(".js") || url.endsWith(".json"))
data = blob.toString(); // allow JS/etc to be written in UTF-8
else
data = blob.toString("binary")
return Promise.resolve(data);
}

// If file should be evaluated, try and do it...
function evaluateFile(file) {
var hsStart = 'require("heatshrink").decompress(atob("';
Expand All @@ -132,16 +100,9 @@ function evaluateFile(file) {
}

Promise.all(APPS.map(appid => {
try {
var app = JSON.parse(fs.readFileSync(APPDIR + "/" + appid + "/metadata.json").toString());
} catch (e) {
throw new Error(`App ${appid} not found`);
}
return AppInfo.getFiles(app, {
fileGetter : fileGetter,
settings : SETTINGS,
device : { id : DEVICE }
}).then(files => {
var app = apploader.apps.find(a => a.id==appid);
if (!app) throw new Error(`App ${appid} not found`);
return apploader.getAppFiles(app).then(files => {
appfiles = appfiles.concat(files);
});
})).then(() => {
Expand Down
82 changes: 82 additions & 0 deletions bin/lib/apploader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/* Node.js library with utilities to handle using the app loader from node.js */

var DEVICEID = "BANGLEJS2";
var MINIFY = true; // minify JSON?
var BASE_DIR = __dirname + "/../..";
var APPSDIR = BASE_DIR+"/apps/";

//eval(require("fs").readFileSync(__dirname+"../core/js/utils.js"));
var Espruino = require(__dirname + "/../../core/lib/espruinotools.js");
//eval(require("fs").readFileSync(__dirname + "/../../core/lib/espruinotools.js").toString());
//eval(require("fs").readFileSync(__dirname + "/../../core/js/utils.js").toString());
var AppInfo = require(__dirname+"/../../core/js/appinfo.js");

var SETTINGS = {
pretokenise : true
};
global.Const = {
/* Are we only putting a single app on a device? If so
apps should all be saved as .bootcde and we write info
about the current app into app.info */
SINGLE_APP_ONLY : false,
};

var apps = [];

// call with {DEVICEID:"BANGLEJS/BANGLEJS2"}
exports.init = function(options) {
if (options.DEVICEID)
DEVICEID = options.DEVICEID;
// Load app metadata
var dirs = require("fs").readdirSync(APPSDIR, {withFileTypes: true});
dirs.forEach(dir => {
var appsFile;
if (dir.name.startsWith("_example") || !dir.isDirectory())
return;
try {
appsFile = require("fs").readFileSync(APPSDIR+dir.name+"/metadata.json").toString();
} catch (e) {
ERROR(dir.name+"/metadata.json does not exist");
return;
}
apps.push(JSON.parse(appsFile));
});
};

exports.AppInfo = AppInfo;
exports.apps = apps;

// used by getAppFiles
function fileGetter(url) {
url = BASE_DIR+"/"+url;
console.log("Loading "+url)
var data;
if (MINIFY && url.endsWith(".json")) {
var f = url.slice(0,-5);
console.log("MINIFYING JSON "+f);
var j = eval("("+require("fs").readFileSync(url).toString("binary")+")");
data = JSON.stringify(j);
} else {
var blob = require("fs").readFileSync(url);
if (url.endsWith(".js") || url.endsWith(".json"))
data = blob.toString(); // allow JS/etc to be written in UTF-8
else
data = blob.toString("binary")
}
return Promise.resolve(data);
}

exports.getAppFiles = function(app) {
return AppInfo.getFiles(app, {
fileGetter:fileGetter,
settings : SETTINGS,
device : { id : DEVICEID }
});
};

// Get all the files for this app as a string of Storage.write commands
exports.getAppFilesString = function(app) {
return exports.getAppFiles(app).then(files => {
return files.map(f=>f.cmd).join("\n")+"\n"
})
};
Loading

0 comments on commit b89a368

Please sign in to comment.