1
0
Fork 0

Added bin/sanitycheck.js to perform a bunch of tests to make sure everything is correct

master
Gordon Williams 2020-02-28 14:17:22 +00:00
parent 122ee5342a
commit 8220765c11
20 changed files with 143 additions and 48 deletions

View File

@ -67,6 +67,10 @@ This is the best way to test...
* Run your personal `Bangle App Loader` at https://\<your-github-username\>.github.io/BangleApps/index.html to load apps onto your device * Run your personal `Bangle App Loader` at https://\<your-github-username\>.github.io/BangleApps/index.html to load apps onto your device
* Your apps should be inside it - if there are problems, check your web browser's 'developer console' for errors * Your apps should be inside it - if there are problems, check your web browser's 'developer console' for errors
**Note:** It's a great idea to get a local copy of the repository on your PC,
then run `bin/sanitycheck.js` - it'll run through a bunch of common issues
that there might be.
Be aware of the delay between commits and updates on github.io - it can take a few minutes (and a 'hard refresh' of your browser) for changes to take effect. Be aware of the delay between commits and updates on github.io - it can take a few minutes (and a 'hard refresh' of your browser) for changes to take effect.
### Offline ### Offline
@ -280,8 +284,6 @@ See [apps/gpsrec/interface.html](the GPS Recorder) for a full example.
## Coding hints ## Coding hints
- Need to save state? Use the `E.on('kill',...)` event to save JSON to a file called `7chname.json`, then load it at startup.
- use `g.setFont(.., size)` to multiply the font size, eg ("6x8",3) : "18x24" - use `g.setFont(.., size)` to multiply the font size, eg ("6x8",3) : "18x24"
- use `g.drawString(text,x,y,true)` to draw with background color to overwrite existing text - use `g.drawString(text,x,y,true)` to draw with background color to overwrite existing text
@ -296,6 +298,13 @@ See [apps/gpsrec/interface.html](the GPS Recorder) for a full example.
- chaining graphics methods, eg `g.setColor(0xFD20).setFontAlign(0,0).setfont("6x8",3)` - chaining graphics methods, eg `g.setColor(0xFD20).setFontAlign(0,0).setfont("6x8",3)`
### Misc Notes
- Need to save state? Use the `E.on('kill',...)` event to save JSON to a file called `7chname.json`, then load it at startup.
- 'Welcome' apps define a file called `welcome.js` which the booloader picks up. This then chain-loads the welcome app itself.
### Graphic areas ### Graphic areas
The screen is parted in a widget and app area for lcd mode `direct`(default). The screen is parted in a widget and app area for lcd mode `direct`(default).

View File

@ -42,9 +42,10 @@
"icon": "app.png", "icon": "app.png",
"version":"0.03", "version":"0.03",
"description": "Appears at first boot and explains how to use Bangle.js", "description": "Appears at first boot and explains how to use Bangle.js",
"tags": "welcome", "tags": "start,welcome",
"allow_emulator":true, "allow_emulator":true,
"storage": [ "storage": [
{"name":"welcome.js","url":"welcome.js"},
{"name":"welcome.app.js","url":"app.js"}, {"name":"welcome.app.js","url":"app.js"},
{"name":"welcome.img","url":"app-icon.js","evaluate":true} {"name":"welcome.img","url":"app-icon.js","evaluate":true}
] ]
@ -210,12 +211,14 @@
}, },
{ "id": "openloc", { "id": "openloc",
"name": "Open Location / Plus Codes", "name": "Open Location / Plus Codes",
"icon": "openlocation.png", "shortName": "Open Location",
"icon": "app.png",
"version":"0.01", "version":"0.01",
"description": "Convert your current GPS location to a series of characters", "description": "Convert your current GPS location to a series of characters",
"tags": "tool,outdoors,gps", "tags": "tool,outdoors,gps",
"storage": [ "storage": [
{"name":"openloc.app.js","url":"openlocation.js","evaluate":true} {"name":"openloc.app.js","url":"app.js"},
{"name":"openloc.img","url":"app-icon.js","evaluate":true}
] ]
}, },
{ "id": "speedo", { "id": "speedo",
@ -304,6 +307,7 @@
"version":"0.01", "version":"0.01",
"description": "When the screen is on, the widget turns on the heart rate monitor and displays the current heart rate (or last known in grey). For this to work well you'll need at least a 15 second LCD Timeout.", "description": "When the screen is on, the widget turns on the heart rate monitor and displays the current heart rate (or last known in grey). For this to work well you'll need at least a 15 second LCD Timeout.",
"tags": "health,widget", "tags": "health,widget",
"type": "widget",
"storage": [ "storage": [
{"name":"widhrm.wid.js","url":"widget.js"} {"name":"widhrm.wid.js","url":"widget.js"}
] ]
@ -333,6 +337,7 @@
}, },
{ "id": "hidmsic", { "id": "hidmsic",
"name": "Bluetooth Music Controls", "name": "Bluetooth Music Controls",
"shortName": "Music Control",
"icon": "hid-music.png", "icon": "hid-music.png",
"version":"0.01", "version":"0.01",
"description": "Enable HID in settings, pair with your phone, then use this app to control music from your watch!", "description": "Enable HID in settings, pair with your phone, then use this app to control music from your watch!",
@ -344,6 +349,7 @@
}, },
{ "id": "hidkbd", { "id": "hidkbd",
"name": "Bluetooth Keyboard", "name": "Bluetooth Keyboard",
"shortName": "Bluetooth Kbd",
"icon": "hid-keyboard.png", "icon": "hid-keyboard.png",
"version":"0.01", "version":"0.01",
"description": "Enable HID in settings, pair with your phone/PC, then use this app to control other apps", "description": "Enable HID in settings, pair with your phone/PC, then use this app to control other apps",
@ -355,6 +361,7 @@
}, },
{ "id": "hidbkbd", { "id": "hidbkbd",
"name": "Binary Bluetooth Keyboard", "name": "Binary Bluetooth Keyboard",
"shortName": "Binary BT Kbd",
"icon": "hid-binary-keyboard.png", "icon": "hid-binary-keyboard.png",
"version":"0.01", "version":"0.01",
"description": "Enable HID in settings, pair with your phone/PC, then type messages using the onscreen keyboard by tapping repeatedly on the key you want", "description": "Enable HID in settings, pair with your phone/PC, then type messages using the onscreen keyboard by tapping repeatedly on the key you want",
@ -392,7 +399,7 @@
"custom": "qrcode.html", "custom": "qrcode.html",
"storage": [ "storage": [
{"name":"qrcode.app.js"}, {"name":"qrcode.app.js"},
{"name":"qrcode.wid.js"} {"name":"qrcode.img"}
] ]
}, },
{ "id": "beer", { "id": "beer",
@ -404,7 +411,7 @@
"custom": "beercompass.html", "custom": "beercompass.html",
"storage": [ "storage": [
{"name":"beer.app.js"}, {"name":"beer.app.js"},
{"name":"beer.wid.js"} {"name":"beer.img"}
] ]
}, },
{ "id": "route", { "id": "route",
@ -416,27 +423,25 @@
"custom": "route.html", "custom": "route.html",
"storage": [ "storage": [
{"name":"route.app.js"}, {"name":"route.app.js"},
{"name":"route.wid.js"} {"name":"route.img"}
] ]
}, },
{ {
"id": "ncstart", "id": "ncstart",
"name": "NCEU Startup", "name": "NCEU Startup",
"icon": "start.png", "icon": "start.png",
"version":"0.02", "version":"0.02",
"description": "NodeConfEU 2019 'First Start' Sequence", "description": "NodeConfEU 2019 'First Start' Sequence",
"tags": "start", "tags": "start,welcome",
"storage": [ "storage": [
{"name":".boot3","url":"start.js"}, {"name":"welcome.js","url":"welcome.js"},
{"name":"ncstart.app.js","url":"start.js"},
{"name":"ncstart.img","url":"start-icon.js","evaluate":true}, {"name":"ncstart.img","url":"start-icon.js","evaluate":true},
{"name":"bangle.img","url":"start-bangle.js","evaluate":true}, {"name":"nc-bangle.img","url":"start-bangle.js","evaluate":true},
{"name":"nceu.img","url":"start-nceu.js","evaluate":true}, {"name":"nc-nceu.img","url":"start-nceu.js","evaluate":true},
{"name":"nfr.img","url":"start-nfr.js","evaluate":true}, {"name":"nc-nfr.img","url":"start-nfr.js","evaluate":true},
{"name":"nodew.img","url":"start-nodew.js","evaluate":true}, {"name":"nc-nodew.img","url":"start-nodew.js","evaluate":true},
{"name":"tf.img","url":"start-tf.js","evaluate":true} {"name":"nc-tf.img","url":"start-tf.js","evaluate":true}
] ]
}, },
{ "id": "ncfrun", { "id": "ncfrun",
@ -637,9 +642,8 @@
"tags": "gps", "tags": "gps",
"type": "app", "type": "app",
"storage": [ "storage": [
{"name": "+gpsinfo","url": "gps-info.json"}, {"name":"gpsinfo.app.js","url": "gps-info.js"},
{"name": "-gpsinfo","url": "gps-info.js"}, {"name":"gpsinfo.img","url": "gps-info-icon.js","evaluate": true}
{"name": "*gpsinfo","url": "gps-info-icon.js","evaluate": true}
] ]
}, },
{ {
@ -652,13 +656,13 @@
"type": "app", "type": "app",
"allow_emulator":true, "allow_emulator":true,
"storage": [ "storage": [
{"name": "+pomodo","url": "pomodoro.json"}, {"name":"pomodo.app.js","url": "pomodoro.js"},
{"name": "-pomodo","url": "pomodoro.js"}, {"name":"pomodo.img","url": "pomodoro-icon.js","evaluate": true}
{"name": "*pomodo","url": "pomodoro-icon.js","evaluate": true}
] ]
}, },
{ "id": "blobclk", { "id": "blobclk",
"name": "Large Digit Blob Clock", "name": "Large Digit Blob Clock",
"shortName" : "Blob Clock",
"icon": "clock-blob.png", "icon": "clock-blob.png",
"version":"0.03", "version":"0.03",
"description": "A clock with big digits", "description": "A clock with big digits",

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AH4Az4/HDDAACCywaSCpgeLBQOjzowRIxZPMBIWj0YvjNRKQSCpIWBEBq/VF6hrKdpwuKABYvXFywlDXjw5aF1gvKF0gv5F0ovvFxQxkF9ztLF8ItJF5XGAAIrfeJYtB4D7TFyQlEFwg8INgZtFF6wuCF4wAFBoPAF7ouNF8AfCF56ZFFyofEF9YgCF5z6GF9y+TC4SAFF9ZgNBgovZMAeczgRJBYovXMAtPAAIQIBYouXDAWjEYUrGBMrBYgvY/15vNVCtAADqoACCs4A/AH4A/AH4A/ABY") require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AH4Az4/HDDAACCywaSCpgeLBQOjzowRIxZPMBIWj0YvjNRKQSCpIWBEBq/VF6hrKdpwuKABYvXFywlDXjw5aF1gvKF0gv5F0ovvFxQxkF9ztLF8ItJF5XGAAIrfeJYtB4D7TFyQlEFwg8INgZtFF6wuCF4wAFBoPAF7ouNF8AfCF56ZFFyofEF9YgCF5z6GF9y+TC4SAFF9ZgNBgovZMAeczgRJBYovXMAtPAAIQIBYouXDAWjEYUrGBMrBYgvY/15vNVCtAADqoACCs4A/AH4A/AH4A/ABY"))

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AH4A/ACXJ5PKAQfKAAPJB4nDAAIsaEwQAJ5IrCAAYbFGyBWBFyooCGxQABPAyDEABYuHGxInFAAQGGLyoIGLxQvCFyAvJBIzjKdB6OLagYwDc5K/DFyIVBAAprHF5IsTHaAuKRoSOSABwvMXyZhPF5iNfF9nJp9PGB4vh5PD3u8X86PCFwO8AAS/mGQe9zAACF/CPdF4aPD3rwmGAu9FxRghegQuKL8IvBFxYwhFx6QdFpxedXIIuQLpHJ4YdCBoQDDFQosRLxAaB4YAEIRIQDFyQvEFhYwGCQgvX/wcOCYYuWDYSmCF6CfEF6mlz96vX+z+evVPCZwABCJYAJvVVAAVPAAYTNCJoAJFwYvPCY5gUAH4A/AH4A/AH4A2") require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AH4A/ACXJ5PKAQfKAAPJB4nDAAIsaEwQAJ5IrCAAYbFGyBWBFyooCGxQABPAyDEABYuHGxInFAAQGGLyoIGLxQvCFyAvJBIzjKdB6OLagYwDc5K/DFyIVBAAprHF5IsTHaAuKRoSOSABwvMXyZhPF5iNfF9nJp9PGB4vh5PD3u8X86PCFwO8AAS/mGQe9zAACF/CPdF4aPD3rwmGAu9FxRghegQuKL8IvBFxYwhFx6QdFpxedXIIuQLpHJ4YdCBoQDDFQosRLxAaB4YAEIRIQDFyQvEFhYwGCQgvX/wcOCYYuWDYSmCF6CfEF6mlz96vX+z+evVPCZwABCJYAJvVVAAVPAAYTNCJoAJFwYvPCY5gUAH4A/AH4A/AH4A2"))

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AGesAAQuuGAQ1jFQoAKF1wwdFyQycF6wwVFi4wWEiOBq1WqoABvQHBvWALsl6p4ADF4IIBGwSNjMAJdCAAVVGwQwPXjWBFoMrF4IwOFzVWp94lV4vIwNFzS8CvGi0YFCGBSNadohdCF9gAGdsgvuGJTvkGAgABFxv+wAwcAAQsLAAVPF9lPAAOIF1tWF7qMOp4DBxAABXtIADGAWB0oupGAeAvQABwJmGAwmlwQuZAAQuCF4SYDAgRtBBoeswKsDF7gsEF4+BqovfAANWF5VWFwIvZGAf+EAYuDBooOEF8ANJF/4vREIQv7BxIvZEIwvvBwQveEIIEDF9QA/AH4A/AH4ASA=") require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AGesAAQuuGAQ1jFQoAKF1wwdFyQycF6wwVFi4wWEiOBq1WqoABvQHBvWALsl6p4ADF4IIBGwSNjMAJdCAAVVGwQwPXjWBFoMrF4IwOFzVWp94lV4vIwNFzS8CvGi0YFCGBSNadohdCF9gAGdsgvuGJTvkGAgABFxv+wAwcAAQsLAAVPF9lPAAOIF1tWF7qMOp4DBxAABXtIADGAWB0oupGAeAvQABwJmGAwmlwQuZAAQuCF4SYDAgRtBBoeswKsDF7gsEF4+BqovfAANWF5VWFwIvZGAf+EAYuDBooOEF8ANJF/4vREIQv7BxIvZEIwvvBwQveEIIEDF9QA/AH4A/AH4ASA="))

View File

@ -3,7 +3,7 @@ E.setFlags({pretokenise:1});
// Load settings... // Load settings...
var s = require('Storage').readJSON('setting.json')||{}; var s = require('Storage').readJSON('setting.json')||{};
if (s.ble!==false) { if (s.ble!==false) {
if (s.HID) { // Humen interface device if (s.HID) { // Human interface device
Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA==")); Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA=="));
NRF.setServices({}, {uart:true, hid:Bangle.HID}); NRF.setServices({}, {uart:true, hid:Bangle.HID});
} }

View File

@ -1,8 +1,8 @@
// This runs after a 'fresh' boot // This runs after a 'fresh' boot
var settings={}; var settings={};
try { settings = require("Storage").readJSON('setting.json'); } catch (e) {} try { settings = require("Storage").readJSON('setting.json'); } catch (e) {}
if (!settings.welcomed && require("Storage").read("-welcome")!==undefined) { if (!settings.welcomed && require("Storage").read("welcome.js")!==undefined) {
setTimeout(()=>load("-welcome")); setTimeout(()=>load("welcome.js"));
} else { } else {
// load clock if specified // load clock if specified
var clockApp = settings.clock; var clockApp = settings.clock;

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("mEwgRC/AH4A/gED/k/5/wh/wgAFCBcg7NgAVBh/zDoYLkHaAFqAH4A/AH4AW")); require("heatshrink").decompress(atob("mEwgRC/AH4A/gED/k/5/wh/wgAFCBcg7NgAVBh/zDoYLkHaAFqAH4A/AH4AW"))

View File

@ -0,0 +1,5 @@
{
"recording":false,
"file":0,
"period":1
}

View File

@ -1,5 +1,3 @@
NRF.sleep();
var g = Graphics.getInstance();
g.setFontAlign(1, 1, 0); g.setFontAlign(1, 1, 0);
const d = g.getWidth() - 18; const d = g.getWidth() - 18;
function c(a) { function c(a) {
@ -53,7 +51,7 @@ function logos() {
]; ];
function next() { function next() {
var n = logos.shift(); var n = logos.shift();
var img = require("Storage").read("*"+n[0]); var img = require("Storage").read("nc-"+n[0]+".img");
g.clear(); g.clear();
g.drawImage(img, n[1], n[2]); g.drawImage(img, n[1], n[2]);
n[3](); n[3]();
@ -117,16 +115,11 @@ function info() {
} }
function cleanup() { function cleanup() {
E.showMessage('Loading...'); try {
var s = require('Storage'); var settings = require("Storage").readJSON('setting.json');
s.erase('*nfr'); settings.welcomed = true;
s.erase('*nceu'); require("Storage").write('setting.json',settings);
s.erase('*bangle'); } catch (e) {}
s.erase('*nodew');
s.erase('*tf');
s.erase('+ncstart');
s.erase('.boot3');
s.erase('*ncstart');
return Promise.resolve(); return Promise.resolve();
} }

1
apps/ncstart/welcome.js Normal file
View File

@ -0,0 +1 @@
eval(require("Storage").read("ncstart.app.js"))

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1 +1 @@
var img = require("heatshrink").decompress(atob("mEwxH+AC4fDDjAuSgwACGFIuBhgACGAJjmLoQvDGAJkhbAguGGYwxbRAoAMGDZZMGBAvSbIpdSGCxYCW5jpDHhKSRDYQgGAwY8ETZYvPDZBXEAAwUFNAowOF44bFNJI2ENISRQdIqzLYhAxDAoRgScZgwFdow1DF54tQdpRMDF5jjHLiDxWF44wJBZIJFF5qPGF5blDLxIvPeAjsOF7RgCc6QvId6AvUd5QACF5pyEKAwlGF5qORcIwoFBgIwHFwwvTU4gvILxYuOXwouKA5AwGFxzuIDYYvkDQ6GIABKqEL6ryGF8QbHF6QXFX6wvuYIQvnFJgMBAAQva/wgMBQT4CF5QPCeB65CABgwCHxYuOF6L5JHYYuPSAyDFBRS6TMA4AME4RdHFyhgCLRLoJLzBgDExa7JFywwVFzQwTFwIADGDC5NRohDBSTQdCGCARCGDRNCGRQuFSobAYGAYxIFwoTDGKpMGWggADA4Q1FYipNGGA7NHYawVBD44qDGIbEHIwwlEA=")) require("heatshrink").decompress(atob("mEwxH+AC4fDDjAuSgwACGFIuBhgACGAJjmLoQvDGAJkhbAguGGYwxbRAoAMGDZZMGBAvSbIpdSGCxYCW5jpDHhKSRDYQgGAwY8ETZYvPDZBXEAAwUFNAowOF44bFNJI2ENISRQdIqzLYhAxDAoRgScZgwFdow1DF54tQdpRMDF5jjHLiDxWF44wJBZIJFF5qPGF5blDLxIvPeAjsOF7RgCc6QvId6AvUd5QACF5pyEKAwlGF5qORcIwoFBgIwHFwwvTU4gvILxYuOXwouKA5AwGFxzuIDYYvkDQ6GIABKqEL6ryGF8QbHF6QXFX6wvuYIQvnFJgMBAAQva/wgMBQT4CF5QPCeB65CABgwCHxYuOF6L5JHYYuPSAyDFBRS6TMA4AME4RdHFyhgCLRLoJLzBgDExa7JFywwVFzQwTFwIADGDC5NRohDBSTQdCGCARCGDRNCGRQuFSobAYGAYxIFwoTDGKpMGWggADA4Q1FYipNGGA7NHYawVBD44qDGIbEHIwwlEA="))

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("mEwxH+64A/AH4A/AH4AllYADqAADugAD4QAD5wADxgADnwADF/4v/F/4vMFQg0EFScyAAYv/F/4v/F5l0AAYqEGggqOlgADF/4v/F/4vMFQnOAAYqEGggqJmgADF/4v/F/4vMFRM+AAYqEGggqEnYADF/4v/F/4vMFR0sAAYqEGglrAAYv/F/4v/F5gqTnYADFQg0EF/4v/F/4vMAH4A/AH4A/AH4AIA")); require("heatshrink").decompress(atob("mEwxH+64A/AH4A/AH4AllYADqAADugAD4QAD5wADxgADnwADF/4v/F/4vMFQg0EFScyAAYv/F/4v/F5l0AAYqEGggqOlgADF/4v/F/4vMFQnOAAYqEGggqJmgADF/4v/F/4vMFRM+AAYqEGggqEnYADF/4v/F/4vMFR0sAAYqEGglrAAYv/F/4v/F5gqTnYADFQg0EF/4v/F/4vMAH4A/AH4A/AH4AIA"))

1
apps/welcome/welcome.js Normal file
View File

@ -0,0 +1 @@
eval(require("Storage").read("welcome.app.js"))

82
bin/sanitycheck.js Normal file
View File

@ -0,0 +1,82 @@
#!/usr/bin/nodejs
/* Checks for any obvious problems in apps.json
*/
var fs = require("fs");
var acorn;
try {
acorn = require("acorn");
} catch (e) {
console.log("=====================================================");
console.log(" ACORN NOT FOUND");
console.log(" ---------------");
console.log("");
console.log(" This means we won't sanity-check uploaded JSON");
console.log("=====================================================");
}
var BASEDIR = __dirname+"/../";
var APPSDIR = BASEDIR+"apps/";
function ERROR(s) {
console.error(s);
process.exit(1);
}
function WARN(s) {
console.log(s);
}
var appsFile, apps;
try {
appsFile = fs.readFileSync(BASEDIR+"apps.json");
} catch (e) {
ERROR("apps.json not found");
}
try{
apps = JSON.parse(appsFile);
} catch (e) {
ERROR("apps.json not valid JSON");
}
apps.forEach((app,addIdx) => {
if (!app.id) ERROR(`App ${appIdx} has no id`);
console.log(`Checking ${app.id}...`);
var appDir = APPSDIR+app.id+"/";
if (!fs.existsSync(APPSDIR+app.id)) ERROR(`App ${app.id} has no directory`);
if (!app.name) ERROR(`App ${app.id} has no name`);
var isApp = !app.type || app.type=="app";
if (app.name.length>20 && !app.shortName && isApp) ERROR(`App ${app.id} has a long name, but no shortName`);
if (!app.version) WARN(`App ${app.id} has no version`);
if (!app.description) ERROR(`App ${app.id} has no description`);
if (!app.icon) ERROR(`App ${app.id} has no icon`);
if (!fs.existsSync(appDir+app.icon)) ERROR(`App ${app.id} icon doesn't exist`);
if (app.custom && !fs.existsSync(appDir+app.custom)) ERROR(`App ${app.id} custom HTML doesn't exist`);
if (app.interface && !fs.existsSync(appDir+app.interface)) ERROR(`App ${app.id} interface HTML doesn't exist`);
var fileNames = [];
app.storage.forEach((file) => {
if (!file.name) ERROR(`App ${app.id} has a file with no name`);
if (fileNames.includes(file.name))
ERROR(`App ${app.id} file ${file.name} is a duplicate`);
fileNames.push(file.name);
if (file.url) if (!fs.existsSync(appDir+file.url)) ERROR(`App ${app.id} file ${file.url} doesn't exist`);
if (!file.url && !file.content && !app.custom) ERROR(`App ${app.id} file ${file.name} has no contents`);
if (file.evaluate) {
var fileContents = file.content ? file.content : fs.readFileSync(appDir+file.url).toString();
try {
acorn.parse("("+fileContents+")");
} catch(e) {
console.log("=====================================================");
console.log(" PARSE OF "+appDir+file.url+" failed.");
console.log("");
console.log(e);
console.log("=====================================================");
console.log(fileContents);
console.log("=====================================================");
ERROR(`App ${app.id}'s ${file.name} has evaluate:true but is not valid JS expression`);
}
}
});
//console.log(fileNames);
if (isApp && !fileNames.includes(app.id+".app.js")) ERROR(`App ${app.id} has no entrypoint`);
if (isApp && !fileNames.includes(app.id+".img")) ERROR(`App ${app.id} has no JS icon`);
if (app.type=="widget" && !fileNames.includes(app.id+".wid.js")) ERROR(`Widget ${app.id} has no entrypoint`);
});

View File

@ -3,7 +3,7 @@ Puck.debug=3;
// FIXME: use UART lib so that we handle errors properly // FIXME: use UART lib so that we handle errors properly
var Comms = { var Comms = {
reset : () => new Promise((resolve,reject) => { reset : () => new Promise((resolve,reject) => {
Puck.write("\x03reset();\n", (result) => { Puck.write("\x03\x10reset();\n", (result) => {
if (result===null) return reject(""); if (result===null) return reject("");
setTimeout(resolve,500); setTimeout(resolve,500);
}); });

View File

@ -51,7 +51,7 @@
<div class="container" style="padding-top:4px"> <div class="container" style="padding-top:4px">
<p><span class="label label-error">App Loader is incompatible with 'old' Bangle.js firmwares</span> <p><span class="label label-error">App Loader is incompatible with 'old' Bangle.js firmwares</span>
Please <a href="https://www.espruino.com/Bangle.js#firmware-updates" target="_blank">(<a href="http://forum.espruino.com/conversations/344251/" target="_blank">more info</a>)Update to the latest firmware</a> or <a href="https://www.espruino.com/Bangle.js#firmware-updates" target="_blank">(<a href="http://forum.espruino.com/conversations/344251/" target="_blank">more info</a>) Please update to the latest firmware</a> or
<a href="https://banglejs.com/oldapps/">use the legacy apps</a>. <a href="https://banglejs.com/oldapps/">use the legacy apps</a>.
</p> </p>
</div> </div>