mirror of https://github.com/espruino/BangleApps
boot 0.23: Move to a precalculated .boot0 file which should speed up load time
setting 0.25: Move boot.js code into 'boot' app itself launch 0.05: Use g.theme for colours widbat 0.06: Use 'g.theme' (requires bootloader 0.23) widlock: new widgetpull/756/head
parent
03d580160d
commit
1dca641ff0
25
apps.json
25
apps.json
|
@ -4,11 +4,12 @@
|
|||
"tags": "tool,system",
|
||||
"type":"bootloader",
|
||||
"icon": "bootloader.png",
|
||||
"version":"0.22",
|
||||
"version":"0.23",
|
||||
"description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings",
|
||||
"storage": [
|
||||
{"name":".boot0","url":"boot0.js"},
|
||||
{"name":".bootcde","url":"bootloader.js"}
|
||||
{"name":".bootcde","url":"bootloader.js"},
|
||||
{"name":"bootupdate.js","url":"bootupdate.js"}
|
||||
],
|
||||
"sortorder" : -10
|
||||
},
|
||||
|
@ -41,7 +42,7 @@
|
|||
"name": "Launcher (Default)",
|
||||
"shortName":"Launcher",
|
||||
"icon": "app.png",
|
||||
"version":"0.04",
|
||||
"version":"0.05",
|
||||
"description": "This is needed by Bangle.js to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.",
|
||||
"tags": "tool,system,launcher",
|
||||
"type":"launch",
|
||||
|
@ -171,13 +172,12 @@
|
|||
{ "id": "setting",
|
||||
"name": "Settings",
|
||||
"icon": "settings.png",
|
||||
"version":"0.24",
|
||||
"version":"0.25",
|
||||
"description": "A menu for setting up Bangle.js",
|
||||
"tags": "tool,system",
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"setting.app.js","url":"settings.js"},
|
||||
{"name":"setting.boot.js","url":"boot.js"},
|
||||
{"name":"setting.img","url":"settings-icon.js","evaluate":true}
|
||||
],
|
||||
"data": [
|
||||
|
@ -571,7 +571,7 @@
|
|||
{ "id": "widbat",
|
||||
"name": "Battery Level Widget",
|
||||
"icon": "widget.png",
|
||||
"version":"0.05",
|
||||
"version":"0.06",
|
||||
"description": "Show the current battery level and charging status in the top right of the clock",
|
||||
"tags": "widget,battery",
|
||||
"type":"widget",
|
||||
|
@ -579,6 +579,17 @@
|
|||
{"name":"widbat.wid.js","url":"widget.js"}
|
||||
]
|
||||
},
|
||||
{ "id": "widlock",
|
||||
"name": "Lock Widget",
|
||||
"icon": "widget.png",
|
||||
"version":"0.01",
|
||||
"description": "On devices with always-on display (Bangle.js 2) this displays lock icon whenever the display is locked",
|
||||
"tags": "widget,lock",
|
||||
"type":"widget",
|
||||
"storage": [
|
||||
{"name":"widlock.wid.js","url":"widget.js"}
|
||||
]
|
||||
},
|
||||
{ "id": "widbatpc",
|
||||
"name": "Battery Level Widget (with percentage)",
|
||||
"shortName": "Battery Widget",
|
||||
|
@ -3123,7 +3134,7 @@
|
|||
{"name":"gps.kit.js","url":"gps.kit.js"},
|
||||
{"name":"digi.kit.js","url":"digi.kit.js"},
|
||||
{"name":"heart.kit.js","url":"heart.kit.js"},
|
||||
{"name":"swatch.kit.js","url":"swatch.kit.js"},
|
||||
{"name":"swatch.kit.js","url":"swatch.kit.js"},
|
||||
{"name":"compass.kit.js","url":"compass.kit.js"},
|
||||
{"name":"kitchen.img","url":"kitchen.icon.js","evaluate":true}
|
||||
],
|
||||
|
|
|
@ -21,3 +21,4 @@
|
|||
0.20: Allow Gadgetbridge to work even with programmable:off
|
||||
0.21: Handle echo off char from Gadgetbridge app when programmable:off (fix #558)
|
||||
0.22: Stop LCD timeout being disabled on first run (when there is no settings.json)
|
||||
0.23: Move to a precalculated .boot0 file which should speed up load time
|
||||
|
|
|
@ -1,68 +1,2 @@
|
|||
// This ALWAYS runs at boot
|
||||
E.setFlags({pretokenise:1});
|
||||
// Load settings...
|
||||
var s = require('Storage').readJSON('setting.json',1)||{};
|
||||
if (s.ble!==false) {
|
||||
if (s.HID) { // Human interface device
|
||||
if (s.HID=="joy") Bangle.HID = E.toUint8Array(atob("BQEJBKEBCQGhAAUJGQEpBRUAJQGVBXUBgQKVA3UBgQMFAQkwCTEVgSV/dQiVAoECwMA="));
|
||||
else if (s.HID=="kb") Bangle.HID = E.toUint8Array(atob("BQEJBqEBBQcZ4CnnFQAlAXUBlQiBApUBdQiBAZUFdQEFCBkBKQWRApUBdQORAZUGdQgVACVzBQcZAClzgQAJBRUAJv8AdQiVArECwA=="));
|
||||
else /*kbmedia*/Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA=="));
|
||||
NRF.setServices({}, {uart:true, hid:Bangle.HID});
|
||||
}
|
||||
}
|
||||
if (s.blerepl===false) { // If not programmable, force terminal off Bluetooth
|
||||
if (s.log) Terminal.setConsole(true); // if showing debug, force REPL onto terminal
|
||||
else E.setConsole(null,{force:true}); // on new (2v05+) firmware we have E.setConsole which allows a 'null' console
|
||||
/* If not programmable add our own handler for Bluetooth data
|
||||
to allow Gadgetbridge commands to be received*/
|
||||
Bluetooth.line="";
|
||||
Bluetooth.on('data',function(d) {
|
||||
var l = (Bluetooth.line + d).split("\n");
|
||||
Bluetooth.line = l.pop();
|
||||
l.forEach(n=>Bluetooth.emit("line",n));
|
||||
});
|
||||
Bluetooth.on('line',function(l) {
|
||||
if (l.startsWith('\x10')) l=l.slice(1);
|
||||
if (l.startsWith('GB({') && l.endsWith('})') && global.GB)
|
||||
try { global.GB(JSON.parse(l.slice(3,-1))); } catch(e) {}
|
||||
});
|
||||
} else {
|
||||
if (s.log && !NRF.getSecurityStatus().connected) Terminal.setConsole(); // if showing debug, put REPL on terminal (until connection)
|
||||
else Bluetooth.setConsole(true); // else if no debug, force REPL to Bluetooth
|
||||
}
|
||||
// we just reset, so BLE should be on.
|
||||
// Don't disconnect if something is already connected to us
|
||||
if (s.ble===false && !NRF.getSecurityStatus().connected) NRF.sleep();
|
||||
// Set time, vibrate, beep, etc
|
||||
if (!Bangle.F_BEEPSET) {
|
||||
if (!s.vibrate) Bangle.buzz=Promise.resolve;
|
||||
if (s.beep===false) Bangle.beep=Promise.resolve;
|
||||
else if (s.beep=="vib") Bangle.beep = function (time, freq) {
|
||||
return new Promise(function(resolve) {
|
||||
if ((0|freq)<=0) freq=4000;
|
||||
if ((0|time)<=0) time=200;
|
||||
if (time>5000) time=5000;
|
||||
analogWrite(D13,0.1,{freq:freq});
|
||||
setTimeout(function() {
|
||||
digitalWrite(D13,0);
|
||||
resolve();
|
||||
}, time);
|
||||
});
|
||||
};
|
||||
}
|
||||
if (s.timeout!==undefined) Bangle.setLCDTimeout(s.timeout);
|
||||
if (!s.timeout) Bangle.setLCDPower(1);
|
||||
E.setTimeZone(s.timezone);
|
||||
delete s;
|
||||
// Draw out of memory errors onto the screen
|
||||
E.on('errorFlag', function(errorFlags) {
|
||||
g.reset(1).setColor("#ff0000").setFont("6x8").setFontAlign(0,1).drawString(errorFlags,g.getWidth()/2,g.getHeight()-1).flip();
|
||||
print("Interpreter error:", errorFlags);
|
||||
E.getErrorFlags(); // clear flags so we get called next time
|
||||
});
|
||||
// stop users doing bad things!
|
||||
global.save = function() { throw new Error("You can't use save() on Bangle.js without overwriting the bootloader!"); }
|
||||
// Load *.boot.js files
|
||||
require('Storage').list(/\.boot\.js/).forEach(bootFile=>{
|
||||
eval(require('Storage').read(bootFile));
|
||||
});
|
||||
// Initially this runs and rewrites itself
|
||||
eval(require('Storage').read('bootupdate.js'));
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/* This rewrites boot0.js based on current settings. If settings changed then it
|
||||
recalculates, but this avoids us doing a whole bunch of reconfiguration most
|
||||
of the time. */
|
||||
E.showMessage("Updating boot0...");
|
||||
var s = require('Storage').readJSON('setting.json',1)||{};
|
||||
var boot = "";
|
||||
var CRC = E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/));
|
||||
boot += `if (E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/))!=${CRC}) { eval(require('Storage').read('bootupdate.js'));} else {\n`;
|
||||
boot += `E.setFlags({pretokenise:1});\n`;
|
||||
if (s.ble!==false) {
|
||||
if (s.HID) { // Human interface device
|
||||
if (s.HID=="joy") boot += `Bangle.HID = E.toUint8Array(atob("BQEJBKEBCQGhAAUJGQEpBRUAJQGVBXUBgQKVA3UBgQMFAQkwCTEVgSV/dQiVAoECwMA="));`;
|
||||
else if (s.HID=="kb") boot += `Bangle.HID = E.toUint8Array(atob("BQEJBqEBBQcZ4CnnFQAlAXUBlQiBApUBdQiBAZUFdQEFCBkBKQWRApUBdQORAZUGdQgVACVzBQcZAClzgQAJBRUAJv8AdQiVArECwA=="));`
|
||||
else /*kbmedia*/boot += `Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA=="));`;
|
||||
boot += `NRF.setServices({}, {uart:true, hid:Bangle.HID});\n`;
|
||||
}
|
||||
}
|
||||
if (s.blerepl===false) { // If not programmable, force terminal off Bluetooth
|
||||
if (s.log) boot += `Terminal.setConsole(true);\n`; // if showing debug, force REPL onto terminal
|
||||
else boot += `E.setConsole(null,{force:true});\n`; // on new (2v05+) firmware we have E.setConsole which allows a 'null' console
|
||||
/* If not programmable add our own handler for Bluetooth data
|
||||
to allow Gadgetbridge commands to be received*/
|
||||
boot += `
|
||||
Bluetooth.line="";
|
||||
Bluetooth.on('data',function(d) {
|
||||
var l = (Bluetooth.line + d).split("\n");
|
||||
Bluetooth.line = l.pop();
|
||||
l.forEach(n=>Bluetooth.emit("line",n));
|
||||
});
|
||||
Bluetooth.on('line',function(l) {
|
||||
if (l.startsWith('\x10')) l=l.slice(1);
|
||||
if (l.startsWith('GB({') && l.endsWith('})') && global.GB)
|
||||
try { global.GB(JSON.parse(l.slice(3,-1))); } catch(e) {}
|
||||
});\n`;
|
||||
} else {
|
||||
if (s.log) boot += `if (!NRF.getSecurityStatus().connected) Terminal.setConsole();\n`; // if showing debug, put REPL on terminal (until connection)
|
||||
else boot += `Bluetooth.setConsole(true);\n`; // else if no debug, force REPL to Bluetooth
|
||||
}
|
||||
// we just reset, so BLE should be on.
|
||||
// Don't disconnect if something is already connected to us
|
||||
if (s.ble===false) boot += `if (!NRF.getSecurityStatus().connected) NRF.sleep();\n`;
|
||||
// Set time
|
||||
if (s.timeout!==undefined) boot += `Bangle.setLCDTimeout(${s.timeout});\n`;
|
||||
if (!s.timeout) boot += `Bangle.setLCDPower(1);\n`;
|
||||
boot += `E.setTimeZone(${s.timezone});`;
|
||||
// Set vibrate, beep, etc IF on older firmwares
|
||||
if (!Bangle.F_BEEPSET) {
|
||||
if (!s.vibrate) boot += `Bangle.buzz=Promise.resolve;\n`
|
||||
if (s.beep===false) boot += `Bangle.beep=Promise.resolve;\n`
|
||||
else if (s.beep=="vib") boot += `Bangle.beep = function (time, freq) {
|
||||
return new Promise(function(resolve) {
|
||||
if ((0|freq)<=0) freq=4000;
|
||||
if ((0|time)<=0) time=200;
|
||||
if (time>5000) time=5000;
|
||||
analogWrite(D13,0.1,{freq:freq});
|
||||
setTimeout(function() {
|
||||
digitalWrite(D13,0);
|
||||
resolve();
|
||||
}, time);
|
||||
});
|
||||
};\n`;
|
||||
}
|
||||
// Draw out of memory errors onto the screen
|
||||
boot += `E.on('errorFlag', function(errorFlags) {
|
||||
g.reset(1).setColor("#ff0000").setFont("6x8").setFontAlign(0,1).drawString(errorFlags,g.getWidth()/2,g.getHeight()-1).flip();
|
||||
print("Interpreter error:", errorFlags);
|
||||
E.getErrorFlags(); // clear flags so we get called next time
|
||||
});\n`;
|
||||
// stop users doing bad things!
|
||||
if (global.save) boot += `global.save = function() { throw new Error("You can't use save() on Bangle.js without overwriting the bootloader!"); }\n`;
|
||||
// Apply any settings-specific stuff
|
||||
if (s.options) boot+=`Bangle.setOptions(${E.toJS(s.options)});\n`;
|
||||
if (s.quiet && s.qmOptions) boot+=`Bangle.setOptions(${E.toJS(s.qmOptions)});\n`;
|
||||
if (s.quiet && s.qmBrightness) {
|
||||
if (s.qmBrightness!=1) boot+=`Bangle.setLCDBrightness(${s.qmBrightness});\n`;
|
||||
} else {
|
||||
if (s.brightness && s.brightness!=1) boot+=`Bangle.setLCDBrightness(${s.brightness});\n`;
|
||||
}
|
||||
if (s.quiet && s.qmTimeout) boot+=`Bangle.setLCDTimeout(${s.qmTimeout});\n`;
|
||||
if (s.passkey!==undefined && s.passkey.length==6) boot+=`NRF.setSecurity({passkey:${s.passkey}, mitm:1, display:1});\n`;
|
||||
if (s.whitelist) boot+=`NRF.on('connect', function(addr) { if (!(require('Storage').readJSON('setting.json',1)||{}).whitelist.includes(addr)) NRF.disconnect(); });\n`;
|
||||
// Pre-2v10 firmwares without a theme
|
||||
if (!g.theme) {
|
||||
boot += `g.theme={fg:-1,bg:0,fg2:-1,bg2:7,fgH:-1,bgH:0x02F7};\n`;
|
||||
}
|
||||
// Append *.boot.js files
|
||||
require('Storage').list(/\.boot\.js/).forEach(bootFile=>{
|
||||
boot += "//"+bootFile+"\n"+require('Storage').read(bootFile)+"\n";
|
||||
});
|
||||
boot += "}\n";// initial 'if'
|
||||
var s = require('Storage').write('.boot0',boot);
|
||||
delete boot;
|
||||
E.showMessage("Reloading...");
|
||||
eval(require('Storage').read('.boot0'));
|
||||
eval(require('Storage').read('.bootcde'));
|
|
@ -2,3 +2,4 @@
|
|||
0.02: Only store relevant app data (saves RAM when many apps)
|
||||
0.03: Allow scrolling to wrap around (fix #382)
|
||||
0.04: Now displays widgets
|
||||
0.05: Use g.theme for colours
|
||||
|
|
|
@ -12,35 +12,36 @@ var menuScroll = 0;
|
|||
var menuShowing = false;
|
||||
|
||||
function drawMenu() {
|
||||
g.setFont("6x8",2);
|
||||
g.setFontAlign(-1,0);
|
||||
var n = 3;
|
||||
g.reset().setFont("6x8",2).setFontAlign(-1,0);
|
||||
var w = g.getWidth();
|
||||
var h = g.getHeight();
|
||||
var m = w/2;
|
||||
var n = (h-48)/64;
|
||||
if (selected>=n+menuScroll) menuScroll = 1+selected-n;
|
||||
if (selected<menuScroll) menuScroll = selected;
|
||||
// arrows
|
||||
g.setColor(menuScroll ? -1 : 0);
|
||||
g.fillPoly([120,6,106,20,134,20]);
|
||||
g.setColor((apps.length>n+menuScroll) ? -1 : 0);
|
||||
g.fillPoly([120,233,106,219,134,219]);
|
||||
g.setColor(menuScroll ? g.theme.fg : g.theme.bg);
|
||||
g.fillPoly([m,6,m-14,20,m+14,20]);
|
||||
g.setColor((apps.length>n+menuScroll) ? g.theme.fg : g.theme.bg);
|
||||
g.fillPoly([m,h-7,m-14,h-21,m+14,h-21]);
|
||||
// draw
|
||||
g.setColor(-1);
|
||||
g.setColor(g.theme.fg);
|
||||
for (var i=0;i<n;i++) {
|
||||
var app = apps[i+menuScroll];
|
||||
if (!app) break;
|
||||
var y = 24+i*64;
|
||||
if (i+menuScroll==selected) {
|
||||
g.setColor(0.3,0.3,0.3);
|
||||
g.fillRect(0,y,239,y+63);
|
||||
g.setColor(1,1,1);
|
||||
g.drawRect(0,y,239,y+63);
|
||||
g.setColor(g.theme.bgH).fillRect(0,y,w-1,y+63);
|
||||
g.setColor(g.theme.fgH).drawRect(0,y,w-1,y+63);
|
||||
} else
|
||||
g.clearRect(0,y,239,y+63);
|
||||
g.clearRect(0,y,w-1,y+63);
|
||||
g.drawString(app.name,64,y+32);
|
||||
var icon=undefined;
|
||||
if (app.icon) icon = s.read(app.icon);
|
||||
if (icon) try {g.drawImage(icon,8,y+8);} catch(e){}
|
||||
}
|
||||
}
|
||||
g.clear();
|
||||
drawMenu();
|
||||
setWatch(function() {
|
||||
selected--;
|
||||
|
|
|
@ -27,3 +27,4 @@
|
|||
0.22: Move HID to BLE menu
|
||||
0.23: Change max time offset to 13 for NZ summer daylight time (NZDT)
|
||||
0.24: Add Quiet Mode settings
|
||||
0.25: Move boot.js code into 'boot' app itself
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
(() => {
|
||||
var settings = require('Storage').readJSON('setting.json', true);
|
||||
if (!settings) return;
|
||||
if (settings.options) Bangle.setOptions(settings.options);
|
||||
if (settings.quiet && settings.qmOptions) Bangle.setOptions(settings.qmOptions);
|
||||
if (settings.quiet && settings.qmBrightness) {
|
||||
if (settings.qmBrightness!=1) Bangle.setLCDBrightness(settings.qmBrightness);
|
||||
} else {
|
||||
if (settings.brightness && settings.brightness!=1) Bangle.setLCDBrightness(settings.brightness);
|
||||
}
|
||||
if (settings.quiet && settings.qmTimeout) Bangle.setLCDTimeout(s.qmTimeout);
|
||||
if (settings.passkey!==undefined && settings.passkey.length==6) NRF.setSecurity({passkey:settings.passkey, mitm:1, display:1});
|
||||
if (settings.whitelist) NRF.on('connect', function(addr) { if (!settings.whitelist.includes(addr)) NRF.disconnect(); });
|
||||
delete settings;
|
||||
})()
|
|
@ -2,3 +2,4 @@
|
|||
0.03: Tweaks for variable size widget system
|
||||
0.04: Ensure redrawing works with variable size widget system
|
||||
0.05: Fix regression stopping correct widget updates
|
||||
0.06: Use 'g.theme' (requires bootloader 0.23)
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
function draw() {
|
||||
var s = 39;
|
||||
var x = this.x, y = this.y;
|
||||
g.reset();
|
||||
if (Bangle.isCharging()) {
|
||||
g.setColor(CHARGING).drawImage(atob("DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y);
|
||||
x+=16;
|
||||
}
|
||||
g.setColor(-1);
|
||||
g.setColor(g.theme.fg);
|
||||
g.fillRect(x,y+2,x+s-4,y+21);
|
||||
g.clearRect(x+2,y+4,x+s-6,y+19);
|
||||
g.fillRect(x+s-3,y+10,x+s,y+14);
|
||||
g.setColor(CHARGING).fillRect(x+4,y+6,x+4+E.getBattery()*(s-12)/100,y+17);
|
||||
g.setColor(-1);
|
||||
}
|
||||
Bangle.on('charging',function(charging) {
|
||||
if(charging) Bangle.buzz();
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
0.01: First commit
|
|
@ -0,0 +1,10 @@
|
|||
(function(){
|
||||
Bangle.on('lcdPower', function(on) {
|
||||
WIDGETS["lock"].width = Bangle.isLCDOn()?0:16;
|
||||
Bangle.drawWidgets();
|
||||
});
|
||||
WIDGETS["lock"]={area:"tl",width:Bangle.isLCDOn()?0:16,draw:function(w) {
|
||||
if (!Bangle.isLCDOn())
|
||||
g.reset().drawImage(atob("DhABH+D/wwMMDDAwwMf/v//4f+H/h/8//P/z///f/g=="), w.x, w.y);
|
||||
}};
|
||||
})()
|
Binary file not shown.
After Width: | Height: | Size: 728 B |
Loading…
Reference in New Issue