Merge branch 'master' of github.com:espruino/BangleApps

pull/1118/head^2
Gordon Williams 2021-12-16 15:07:10 +00:00
commit d3ccc08209
45 changed files with 708 additions and 305 deletions

View File

@ -1590,7 +1590,7 @@
{
"id": "widpedom",
"name": "Pedometer widget",
"version": "0.19",
"version": "0.20",
"description": "Daily pedometer widget",
"icon": "widget.png",
"type": "widget",
@ -3478,8 +3478,8 @@
{
"id": "speedalt2",
"name": "GPS Adventure Sports II",
"shortName": "GPS Adv Sport II",
"version": "0.07",
"shortName":"GPS Adv Sport II",
"version":"1.10",
"description": "GPS speed, altitude and distance to waypoint display. Designed for easy viewing and use during outdoor activities such as para-gliding, hang-gliding, sailing, cycling etc.",
"icon": "app.png",
"type": "app",
@ -4209,7 +4209,7 @@
"id": "pastel",
"name": "Pastel Clock",
"shortName": "Pastel",
"version": "0.08",
"version": "0.09",
"description": "A Configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times",
"icon": "pastel.png",
"dependencies": {"mylocation":"app", "widpedom":"app"},
@ -4723,8 +4723,9 @@
"id": "pebble",
"name": "Pebble Clock",
"shortName": "Pebble",
"version": "0.04",
"version": "0.06",
"description": "A pebble style clock to keep the rebellion going",
"dependencies": {"widpedom":"app"},
"readme": "README.md",
"icon": "pebble.png",
"screenshots": [{"url":"pebble_screenshot.png"}],
@ -4858,10 +4859,10 @@
"id": "ptlaunch",
"name": "Pattern Launcher",
"shortName": "Pattern Launcher",
"version": "0.10",
"version": "0.11",
"description": "Directly launch apps from the clock screen with custom patterns.",
"icon": "app.png",
"screenshots": [{"url":"main_menu_add.png"}, {"url":"add_pattern.png"}, {"url":"select_app.png"}, {"url":"main_menu_manage.png"}, {"url":"manage_patterns.png"}],
"screenshots": [{"url":"manage_patterns_light.png"}],
"tags": "tools",
"supports": ["BANGLEJS2"],
"readme": "README.md",
@ -4876,11 +4877,11 @@
"id": "rebble",
"name": "Rebble Clock",
"shortName": "Rebble",
"version": "0.02",
"version": "0.03",
"description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion",
"readme": "README.md",
"icon": "rebble.png",
"dependencies": {"mylocation":"app"},
"dependencies": {"mylocation":"app", "widpedom":"app"},
"screenshots": [{"url":"screenshot_rebble.png"}],
"type": "clock",
"tags": "clock",
@ -4918,6 +4919,7 @@
"supports" : ["BANGLEJS", "BANGLEJS2"],
"readme": "README.md",
"storage": [
{"name":"clicompleteclk.app.js","url":"app.js"},
{"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true},
{"name":"clicompleteclk.settings.js","url":"settings.js"}
],
@ -4941,7 +4943,7 @@
{ "id": "pooqround",
"name": "pooq Round watch face",
"shortName":"pooq Round",
"version":"0.00",
"version":"0.01",
"description": "A 24 hour analogue watchface with high legibility and a novel style.",
"icon": "app.png",
"type": "clock",
@ -4977,8 +4979,8 @@
"id": "showimg",
"name": "simple image viewer",
"shortName":"showImage",
"version":"0.1",
"description": "Displays the image file in showimage.user.img. Returns to watch face after 60s or button push. I use it to display my vaccination certificate.",
"version":"0.2",
"description": "Displays the image in \"showimage.user.img\". The file has to be uploaded via the espruino IDE. Returns to watch face after 60s or button push. I use it to display my vaccination certificate.",
"icon": "app.png",
"tags": "tool",
"supports" : ["BANGLEJS2"],
@ -4986,5 +4988,43 @@
{"name":"showimg.app.js","url":"app.js"},
{"name":"showimg.img","url":"app-icon.js","evaluate":true}
]
}
},
{
"id": "lapcounter",
"name": "Lap Counter",
"version": "0.01",
"description": "Click button to count laps. Shows count and total time snapshot (like a stopwatch, but laid back).",
"icon": "app.png",
"screenshots": [{"url":"screenshot.png"}],
"type": "app",
"tags": "tool,outdoors",
"readme":"README.md",
"supports": ["BANGLEJS", "BANGLEJS2"],
"allow_emulator": true,
"storage": [
{"name":"lapcounter.app.js","url":"app.js"},
{"name":"lapcounter.img","url":"app-icon.js","evaluate":true}
]
},
{ "id": "circlesclock",
"name": "Circles clock",
"shortName":"Circles clock",
"version":"0.01",
"description": "A clock with circles for different data at the bottom in a probably familiar style",
"icon": "app.png",
"dependencies": {"widpedom":"app"},
"type": "clock",
"tags": "clock",
"supports" : ["BANGLEJS2"],
"allow_emulator":true,
"readme": "README.md",
"storage": [
{"name":"circlesclock.app.js","url":"app.js"},
{"name":"circlesclock.img","url":"app-icon.js","evaluate":true},
{"name":"circlesclock.settings.js","url":"settings.js"}
],
"data": [
{"name":"circlesclock.json"}
]
}
]

View File

@ -0,0 +1 @@
0.01: New clock

View File

@ -0,0 +1,19 @@
# Circles clock
A clock with circles for different data at the bottom in a probably familiar style
It shows besides time, date and day of week the following information:
* Steps (requires [pedometer widget](https://banglejs.com/apps/#pedometer))
* Heart rate (when screen is on and unlocked)
* Battery
## Screenshot
![Screenshot](screenshot.png)
## TODO
* Show weather information
## Creator
Marco ([myxor](https://github.com/myxor))

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("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"))

218
apps/circlesclock/app.js Normal file
View File

@ -0,0 +1,218 @@
const locale = require("locale");
const heatshrink = require("heatshrink");
var shoesIcon = heatshrink.decompress(atob("h0OwYJGgmAAgUBkgECgVJB4cSoAUDyEBkARDpADBhMAyQRBgVAkgmDhIUDAAuQAgY1DAAYA="));
var heartIcon = heatshrink.decompress(atob("h0OwYOLkmQhMkgACByVJgESpIFBpEEBAIFBCgIFCCgsABwcAgQOCAAMSpAwDyBNM"));
var powerIcon = heatshrink.decompress(atob("h0OwYQNsAED7AEDmwEDtu2AgUbtuABwXbBIUN23AAoYOCgEDFIgODABI"));
const SETTINGS_FILE = "circlesclock.json";
let settings;
function loadSettings() {
settings = require("Storage").readJSON(SETTINGS_FILE, 1) || {
'maxHR': 200,
'stepGoal': 10000
};
}
const colorFg = '#fff';
const colorBg = '#000';
const colorGrey = '#808080';
let hrtValue;
const h = g.getHeight();
const w = g.getWidth();
const hOffset = 30;
const h1 = Math.round(1 * h / 5 - hOffset);
const h2 = Math.round(3 * h / 5 - hOffset);
const h3 = Math.round(8 * h / 8 - hOffset);
const w1 = Math.round(w / 6);
const w2 = Math.round(3 * w / 6);
const w3 = Math.round(5 * w / 6);
const radiusOuter = 22;
const radiusInner = 16;
function draw() {
g.reset();
g.setColor(colorBg);
g.fillRect(0, 0, w, h);
// time
g.setFont("Vector:50");
g.setFontAlign(-1, -1);
g.setColor(colorFg);
g.drawString(locale.time(new Date(), 1), w / 10, h1 + 8);
// date & dow
g.setFont("Vector:20");
g.setFontAlign(-1, 0);
g.drawString(locale.date(new Date()), w / 10, h2);
g.drawString(locale.dow(new Date()), w / 10, h2 + 22);
// Steps circle
drawSteps();
// Heart circle
drawHeartRate();
// Battery circle
drawBattery();
}
function drawSteps() {
const steps = getSteps();
const blue = '#0000ff';
g.setColor(colorGrey);
g.fillCircle(w1, h3, radiusOuter);
const stepGoal = settings.stepGoal;
if (stepGoal > 0) {
let percent = steps / stepGoal;
if (stepGoal < steps) percent = 1;
drawGauge(w1, h3, percent, blue);
}
g.setColor(colorBg);
g.fillCircle(w1, h3, radiusInner);
g.fillPoly([w1, h3, w1 - 15, h3 + radiusOuter + 5, w1 + 15, h3 + radiusOuter + 5]);
g.setFont("Vector:12");
g.setFontAlign(0, 0);
g.setColor(colorFg);
g.drawString(shortValue(steps), w1 + 2, h3);
g.drawImage(shoesIcon, w1 - 6, h3 + radiusOuter - 6);
}
function drawHeartRate() {
const red = '#ff0000';
g.setColor(colorGrey);
g.fillCircle(w2, h3, radiusOuter);
if (hrtValue != undefined) {
const percent = hrtValue / settings.maxHR;
drawGauge(w2, h3, percent, red);
}
g.setColor(colorBg);
g.fillCircle(w2, h3, radiusInner);
g.fillPoly([w2, h3, w2 - 15, h3 + radiusOuter + 5, w2 + 15, h3 + radiusOuter + 5]);
g.setFont("Vector:12");
g.setFontAlign(0, 0);
g.setColor(colorFg);
g.drawString(hrtValue != undefined ? hrtValue : 0, w2, h3);
g.drawImage(heartIcon, w2 - 6, h3 + radiusOuter - 6);
}
function drawBattery() {
const battery = E.getBattery();
const yellow = '#ffff00';
g.setColor(colorGrey);
g.fillCircle(w3, h3, radiusOuter);
if (battery > 0) {
const percent = battery / 100;
drawGauge(w3, h3, percent, yellow);
}
g.setColor(colorBg);
g.fillCircle(w3, h3, radiusInner);
g.fillPoly([w3, h3, w3 - 15, h3 + radiusOuter + 5, w3 + 15, h3 + radiusOuter + 5]);
g.setFont("Vector:12");
g.setFontAlign(0, 0);
g.setColor(colorFg);
g.drawString(battery + '%', w3, h3);
g.drawImage(powerIcon, w3 - 6, h3 + radiusOuter - 6);
}
function radians(a) {
return a * Math.PI / 180;
}
function drawGauge(cx, cy, percent, color) {
let offset = 30;
let end = 300;
var i = 0;
var r = radiusInner + 3;
if (percent > 1) percent = 1;
var startrot = -offset;
var endrot = startrot - ((end - offset) * percent);
g.setColor(color);
// draw gauge
for (i = startrot; i > endrot; i -= 4) {
x = cx + r * Math.sin(radians(i));
y = cy + r * Math.cos(radians(i));
g.fillCircle(x, y, 4);
}
}
function shortValue(v) {
if (isNaN(v)) return '-';
if (v <= 999) return v;
if (v >= 1000 && v < 10000) {
v = Math.floor(v / 100) * 100;
return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
}
if (v >= 10000) {
v = Math.floor(v / 1000) * 1000;
return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
}
}
function getSteps() {
if (WIDGETS.wpedom !== undefined) {
return WIDGETS.wpedom.getSteps();
}
return 0;
}
Bangle.on('lock', function(isLocked) {
if (!isLocked) {
Bangle.setHRMPower(1, "watch");
} else {
Bangle.setHRMPower(0, "watch");
}
drawHeartRate();
drawSteps();
});
Bangle.on('HRM', function(hrm) {
//if(hrm.confidence > 90){
hrtValue = hrm.bpm;
if (Bangle.isLCDOn())
drawHeartRate();
//} else {
// hrtValue = undefined;
//}
});
g.clear();
Bangle.loadWidgets();
/*
* we are not drawing the widgets as we are taking over the whole screen
* so we will blank out the draw() functions of each widget and change the
* area to the top bar doesn't get cleared.
*/
for (let wd of WIDGETS) {
wd.draw = () => {};
wd.area = "";
}
loadSettings();
setInterval(draw, 60000);
draw();
Bangle.setUI("clock");

BIN
apps/circlesclock/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,33 @@
(function(back) {
const SETTINGS_FILE = "circlesclock.json";
const storage = require('Storage');
let settings = storage.readJSON(SETTINGS_FILE, 1) || {};
function save(key, value) {
settings[key] = value;
storage.write(SETTINGS_FILE, settings);
}
E.showMenu({
'': { 'title': 'circlesclock' },
'max heartrate': {
value: "maxHR" in settings ? settings.maxHR : 200,
min: 20,
max : 250,
step: 10,
format: x => {
return x;
},
onchange: x => save('maxHR', x),
},
'step goal': {
value: "stepGoal" in settings ? settings.stepGoal : 10000,
min: 2000,
max : 50000,
step: 2000,
format: x => {
return x;
},
onchange: x => save('stepGoal', x),
},
'< Back': back,
});
});

View File

@ -0,0 +1 @@
0.01: first release

19
apps/lapcounter/README.md Normal file
View File

@ -0,0 +1,19 @@
# Lap Counter
Click button to count laps (e.g. in a swimming pool).
Also shows total duration snapshot (like a stopwatch, but laid back).
![Screenshot](screenshot.png)
## Usage
* Click BTN1 to start counting. Counter becomes `0`, duration becomes `00:00.0`
* Each time you click BTN1, counter is incremented, and you see duration between first and last clicks.
## Features
Disables LCD timeout (so that you can be _sure_ what BTN1 would do).
## Creator
[Nimrod Kerrett](https://zzzen.com)

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwkBiIA/AH4A/AAkQgEBAREAC6oABdZQXkI6wuKC5iPUFxoXIOpoX/C6QFCC6IsCC6ZEDC/4XcPooXOFgoXQIgwX/C7IUFC5wsIC5ouCC6hcJC5h1DF9YwBChCPOAH4A/AH4Ap"))

53
apps/lapcounter/app.js Normal file
View File

@ -0,0 +1,53 @@
const w = g.getWidth();
const h = g.getHeight();
const wid_h = 24;
let tStart;
let tNow;
let counter=-1;
const icon = require("heatshrink").decompress(atob("mEwwkBiIA/AH4A/AAkQgEBAREAC6oABdZQXkI6wuKC5iPUFxoXIOpoX/C6QFCC6IsCC6ZEDC/4XcPooXOFgoXQIgwX/C7IUFC5wsIC5ouCC6hcJC5h1DF9YwBChCPOAH4A/AH4Ap"));
function timeToText(t) { // Courtesy of stopwatch app
let hrs = Math.floor(t/3600000);
let mins = Math.floor(t/60000)%60;
let secs = Math.floor(t/1000)%60;
let tnth = Math.floor(t/100)%10;
let text;
if (hrs === 0)
text = ("0"+mins).substr(-2) + ":" + ("0"+secs).substr(-2) + "." + tnth;
else
text = ("0"+hrs) + ":" + ("0"+mins).substr(-2) + ":" + ("0"+secs).substr(-2);
//log_debug(text);
return text;
}
function doCounter() {
if (counter<0) {
tStart = Date.now();
tNow = tStart;
} else {
tNow = Date.now();
}
counter++;
let dT = tNow-tStart;
g.clearRect(0,wid_h,w,h-wid_h);
g.setFontAlign(0,0);
g.setFont("Vector",72);
g.drawString(counter,w/2,h/2);
g.setFont("Vector",24);
g.drawString(timeToText(dT),w/2,h/2+50);
}
setWatch(doCounter, BTN1, true);
g.clear(true);
Bangle.loadWidgets();
Bangle.drawWidgets();
Bangle.setLCDTimeout(0);
g.drawImage(icon,w/2-24,h/2-24);
g.setFontAlign(0,0);
require("Font8x12").add(Graphics);
g.setFont("8x12");
g.drawString("Click button to count.", w/2, h/2+22);

BIN
apps/lapcounter/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -6,3 +6,4 @@
0.06: Converted fonts to font modules
0.07: Added info line that cycles on BTN1/BTN3 (or vitual buttons on a bangle 2)
0.08: Added dependancy on MyLocation
0.09: Added dependancy on Pedometer Widget

View File

@ -3,3 +3,4 @@
0.03: Changed time+calendar font to LECO1976Regular, changed to slanting boot
0.04: Fix widget hiding code (fix #1046)
0.05: Fix typo in settings - Purple
0.06: Added dependancy on Pedometer Widget

View File

@ -1 +1,2 @@
0.00: Initial check-in.
0.01: Add tap-to-decorate feature. Bugfixes.

View File

@ -10,16 +10,18 @@ Either you'll like that, or you won't.
## Options
Because sometimes I don't want to burn what I'm cooking and others I'm lazy and just want to know if it's afternoon yet,
you can alter the number of hands on the display. When the watch is unlocked, slide up to add dots representing the minute and second,
or down to remove the distraction. There's also a setting that displays the second hand, but only if the watch is perfectly face-to-the-sky,
in case you want the ability to check the _exact_ time, hands free, without the impact on battery life this usually entails.
Although we generally obey the system-wide theming, you can long press on the display for a menu of additional options specific to the face.
We don't observe the system 12/24 setting, since it the design of the face is equally good in either interpretation.
By default, there is a backlight that comes on when you twist your wrist. This, of course, somewhat increases power draw and could be
annoying in an intentionally dark environment, so there is an option to disable it.
If you like an uncluttered display style, you can still bring up the day, date and minute hand transiently with a tap on the watchface (when unlocked).
Similarly, because sometimes I don't want to burn what I'm cooking and others I'm lazy and just want to know if it's afternoon yet,
you can quickly alter the number of hands on the display. When the watch is unlocked, slide up to add dots representing the minute and second,
or down to remove the distraction. There's also a setting that displays the second hand, but only if the watch is perfectly face-to-the-sky,
in case you want the ability to check the _exact_ time, hands free, without the impact on battery life this usually entails.
In some versions of the Bangle.js firmware, the backlight doesn't come on automatically when you twist your wrist. There's currently a workaround
for this integrated into the watchface; you can disable it in the menu, if you prefer.
## Limitations

View File

@ -83,7 +83,6 @@ class Options {
Bangle.removeListener('drag', this.reactivator);
this.emit('done');
}
g.clear(true);
E.showMenu(m);
}
@ -309,7 +308,7 @@ class Round {
buffer: this.c.buffer, transparent: 0
};
this.options = new RoundOptions();
this.timescales = [1000, 0, 60000, 900000];
this.timescales = [1000, [1000, 60000], 60000, 900000];
this.state = {};
// Precomputed polygons for the border areas.
this.tl = [0, 0, 58, 0, 0, 58];
@ -323,13 +322,15 @@ class Round {
this.r = this.xc - this.minR;
}
reset() {this.state = {}; this.g.clear(true);}
reset(clear) {this.state = {}; clear && this.g.clear(true);}
doIcons(which) {
this.state[which] = null;
this.render(new Date()); // Not quite right, I think.
}
enhanceUntil(t) {this.enhance = t;}
pie(f, a0, a1, invert) {
if (!invert) return this.pie(f, a1, a0 + 1, true);
let t0 = Math.tan(a0 * 2 * Math.PI), t1 = Math.tan(a1 * 2 * Math.PI);
@ -369,17 +370,18 @@ class Round {
const g = this.g;
const b = this.b, bI = this.bI;
const c = this.c, cI = this.cI;
const e = d < this.enhance;
const state = this.state;
const options = this.options;
const cal = options.calendric;
const res = options.resolution;
const dow = (cal == 1 || cal > 2) && d.getDay();
const dow = (e || cal == 1 || cal > 2) && d.getDay();
const ts = res < 2 && d.getSeconds();
const tm = res < 3 && d.getMinutes() + ts / 60;
const tm = (e || res < 3) && d.getMinutes() + ts / 60;
const th = d.getHours() + d.getMinutes() / 60;
const dd = cal > 1 && d.getDate();
const dm = cal > 3 && d.getMonth();
const dy = cal > 4 && d.getFullYear();
const dd = (e || cal > 1) && d.getDate();
const dm = (e || cal > 3) && d.getMonth();
const dy = (e || cal > 4) && d.getFullYear();
const xc = this.xc, yc = this.yc, r = this.r;
const dlr = xc * 3/4, dlw = 8, dlhw = 4;
@ -475,7 +477,6 @@ class Clock {
this.timescales = face.timescales;
this.options = face.options;
this.rates = {};
this.faceUp = null;
this.options.on('done', () => this.start());
@ -485,7 +486,6 @@ class Clock {
lock: () => {face.doIcons('locked'); this.active();},
faceUp: up => {
this.conservative = !up;
this.faceUp = up;
this.active();
},
twist: _ => this.options.autolight && Bangle.setLCDPower(true),
@ -504,9 +504,15 @@ class Clock {
this.options.resolution++;
this.rates.clock = this.timescales[this.options.resolution];
this.active();
} else if (this.yX - this.yN < 20 && Date.now() - this.t0 > 500) {
this.stop();
this.options.interact();
} else if (this.yX - this.yN < 20) {
const now = new Date();
if (now - this.t0 < 250) {
face.enhanceUntil(now + 30000);
face.render(now);
} else if (now - this.t0 > 500) {
this.stop();
this.options.interact();
}
}
this.t0 = null;
}
@ -520,7 +526,7 @@ class Clock {
redraw(rate) {
const now = this.updated = new Date();
if (this.refresh) this.face.reset();
if (this.refresh) this.face.reset(true);
this.refresh = false;
rate = this.face.render(now, rate);
if (rate !== this.rates.face) {
@ -535,7 +541,7 @@ class Clock {
this.exception && clearTimeout(this.exception);
this.interval && clearInterval(this.interval);
this.timeout = this.exception = this.interval = this.rate = null;
this.face.reset(); // Cancel any ongoing background rendering
this.face.reset(false); // Cancel any ongoing background rendering
return this;
}

View File

@ -2,3 +2,4 @@
0.02: Turn on lcd when launching an app if the lock screen was disabled in the settings
0.03: Make tap to confirm new pattern more reliable. Also allow for easier creation of single circle patterns.
0.10: Improve the management of existing patterns: Draw the linked pattern on the left hand side of the app name within a scroller, similar to the default launcher. Slighlty clean up the code to make it less horrible.
0.11: Respect theme colors. Fix: Do not pollute global space with internal variables ans functions in boot.js

View File

@ -10,14 +10,21 @@ Then launch the linked apps directly from the clock screen by simply drawing the
## Add Pattern Screenshots
![](main_menu_add.png)
![](add_pattern.png)
![](select_app.png)
![](main_menu_add_light.png)
![](add_pattern_light.png)
![](select_app_light.png)
![](main_menu_add_dark.png)
![](add_pattern_dark.png)
![](select_app_dark.png)
## Manage Pattern Screenshots
![](main_menu_manage.png)
![](manage_patterns.png)
![](main_menu_manage_light.png)
![](manage_patterns_light.png)
![](main_menu_manage_dark.png)
![](manage_patterns_dark.png)
## Detailed Steps

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -119,8 +119,7 @@ var recognizeAndDrawPattern = () => {
return new Promise((resolve) => {
E.showMenu();
g.clear();
g.setColor(0, 0, 0);
CIRCLES.forEach((circle) => drawCircle(circle));
drawCirclesWithPattern([]);
var pattern = [];
@ -369,7 +368,6 @@ var drawAppWithPattern = (i, r, storedPatterns) => {
offset: { x: 1, y: 3 + r.y },
});
g.setColor(0, 0, 0);
if (!storedPattern.wrappedAppName) {
storedPattern.wrappedAppName = g
.wrapString(app.name, g.getWidth() - 64)
@ -490,7 +488,7 @@ var drawCircle = (circle, drawBuffer, scale) => {
log("drawing circle");
log({ x: x, y: y, r: r });
drawBuffer.fillCircle(x, y, r);
drawBuffer.drawCircle(x, y, r);
};
var cachedCirclesDrawings = {};
@ -535,17 +533,15 @@ var drawCirclesWithPattern = (pattern, options) => {
{ msb: true }
);
drawBuffer.setColor(1);
CIRCLES.forEach((circle) => drawCircle(circle, drawBuffer, scale));
drawBuffer.setColor(0);
drawBuffer.setFontAlign(0, 0);
drawBuffer.setFont("6x8", 4 * scale);
drawBuffer.setFont("Vector", 40 * scale);
pattern.forEach((circleIndex, patternIndex) => {
var circle = CIRCLES[circleIndex];
drawBuffer.drawString(
patternIndex + 1,
circle.x * scale,
(circle.x + (scale === 1 ? 1 : 5)) * scale,
circle.y * scale
);
});

View File

@ -1,167 +1,167 @@
var DEBUG = true;
var log = (message) => {
if (DEBUG) {
console.log(JSON.stringify(message));
}
};
var storedPatterns;
var positions = [];
var dragHandler = (position) => {
positions.push(position);
debounce().then(() => {
log(positions.length);
var CIRCLE_RADIUS = 25;
var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS;
var circles = [
{ x: 25, y: 25, i: 0 },
{ x: 87, y: 25, i: 1 },
{ x: 150, y: 25, i: 2 },
{ x: 25, y: 87, i: 3 },
{ x: 87, y: 87, i: 4 },
{ x: 150, y: 87, i: 5 },
{ x: 25, y: 150, i: 6 },
{ x: 87, y: 150, i: 7 },
{ x: 150, y: 150, i: 8 },
];
var pattern = [];
var step = Math.floor(positions.length / 100) + 1;
var p, a, b, circle;
for (var i = 0; i < positions.length; i += step) {
p = positions[i];
circle = circles[0];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(0, 1);
}
}
circle = circles[1];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(1, 1);
}
}
circle = circles[2];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(2, 1);
}
}
circle = circles[3];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(3, 1);
}
}
circle = circles[4];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(4, 1);
}
}
circle = circles[5];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(5, 1);
}
}
circle = circles[6];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(6, 1);
}
}
circle = circles[7];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(7, 1);
}
}
circle = circles[8];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(8, 1);
}
}
}
positions = [];
pattern = pattern.join("");
if (pattern) {
if (storedPatterns[pattern]) {
var app = storedPatterns[pattern].app;
if (!!app && !!app.src) {
if (storedPatterns.settings) {
if (storedPatterns.settings.lockDisabled) {
Bangle.setLCDPower(true);
}
}
Bangle.removeListener("drag", dragHandler);
load(app.src);
}
}
}
});
};
var debounceTimeoutId;
var debounce = (delay) => {
if (debounceTimeoutId) {
clearTimeout(debounceTimeoutId);
}
return new Promise((resolve) => {
debounceTimeoutId = setTimeout(() => {
debounceTimeoutId = undefined;
resolve();
}, delay || 500);
});
};
(function () {
var DEBUG = false;
var log = (message) => {
if (DEBUG) {
console.log(JSON.stringify(message));
}
};
var storedPatterns;
var positions = [];
var dragHandler = (position) => {
positions.push(position);
debounce().then(() => {
log(positions.length);
var CIRCLE_RADIUS = 25;
var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS;
var circles = [
{ x: 25, y: 25, i: 0 },
{ x: 87, y: 25, i: 1 },
{ x: 150, y: 25, i: 2 },
{ x: 25, y: 87, i: 3 },
{ x: 87, y: 87, i: 4 },
{ x: 150, y: 87, i: 5 },
{ x: 25, y: 150, i: 6 },
{ x: 87, y: 150, i: 7 },
{ x: 150, y: 150, i: 8 },
];
var pattern = [];
var step = Math.floor(positions.length / 100) + 1;
var p, a, b, circle;
for (var i = 0; i < positions.length; i += step) {
p = positions[i];
circle = circles[0];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(0, 1);
}
}
circle = circles[1];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(1, 1);
}
}
circle = circles[2];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(2, 1);
}
}
circle = circles[3];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(3, 1);
}
}
circle = circles[4];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(4, 1);
}
}
circle = circles[5];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(5, 1);
}
}
circle = circles[6];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(6, 1);
}
}
circle = circles[7];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(7, 1);
}
}
circle = circles[8];
if (circle) {
a = p.x - circle.x;
b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i);
circles.splice(8, 1);
}
}
}
positions = [];
pattern = pattern.join("");
if (pattern) {
if (storedPatterns[pattern]) {
var app = storedPatterns[pattern].app;
if (!!app && !!app.src) {
if (storedPatterns.settings) {
if (storedPatterns.settings.lockDisabled) {
Bangle.setLCDPower(true);
}
}
Bangle.removeListener("drag", dragHandler);
load(app.src);
}
}
}
});
};
var debounceTimeoutId;
var debounce = (delay) => {
if (debounceTimeoutId) {
clearTimeout(debounceTimeoutId);
}
return new Promise((resolve) => {
debounceTimeoutId = setTimeout(() => {
debounceTimeoutId = undefined;
resolve();
}, delay || 500);
});
};
var sui = Bangle.setUI;
Bangle.setUI = function (mode, cb) {
sui(mode, cb);

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,2 +1,3 @@
0.01: First release
0.02: Fix dependancies, fix type to Purple
0.02: Fix typo to Purple
0.03: Added dependancy on Pedometer Widget

2
apps/showimg/ChangeLog Normal file
View File

@ -0,0 +1,2 @@
0.1: Initial release
0.2: Fixed launcher image

View File

@ -1 +1 @@
E.toArrayBuffer(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAf////AHP/////AH//////AP/8AAAHAP4AAAAHAOAAMAAHAOAAeAAHAOAA+cAHAOAA/+AHAOAA/+AHAOAf/+AHAOA//+AHgOA///AHgOA///gDgOA/z/gDgOAfz/gDgOA///gDgOA///gDgOA//uADgOAf3+ADgOAP/+ADgOAD/8ADwOAB+4ADwOAA8AABwOAAAABBwOA8DgPxwOB/Dg/xwOB/jh/xwOB3zj5xwOB57nzxwOA4/njhwOA4/vHhwOA8f+PB4OAef+PB4OAef8eB4OAPP58A4OAHv/4A4OAH//wA4OAD//AA4OAA/8fn4PDgP///4P//////4P////9/wD///4AAA"))
require("heatshrink").decompress(atob("mEwwkBIf4Aah//BRQAMDowUNC5AARC4YKKL5gTC+B3TCpAyIC5oNBEA4XNJwS4GC55pHC8TEHC57QHC4wSEC5YpEC6YwEC5oEEC5x3DC6ZHbC7PwcYxfNAYYXPJA4XQDAwKEBYQXJIoReHC5gMFAAojBC5QUIC5Y5JMgYXIUQYJFPggXMAwICCBAYXMCAQJDDwQUCC5QOCUwQdEC5QqFDghNFC5wrEC5gQDPgoTCDYYXFMAgXaCQoXJEwZ4FLQbhFC4imDAAglFC5QAGBgYXKIoYWIC5YYFG4ZkDC4YjCYYwAJC4gASC6THFH5pqGAAY"))

View File

@ -1,2 +1,3 @@
0.01: Initial import.
0.07: Add swipe to change screens.
1.06: Misc memory and screen optimisations.

View File

@ -1,11 +1,9 @@
/*
Speed and Altitude [speedalt2]
Mike Bennett mike[at]kereru.com
0.01 : Initial
0.06 : Add Posn screen
0.07 : Add swipe to change screens same as BTN3
1.10 : add inverted colours
*/
var v = '1.05';
var v = '1.10';
/*kalmanjs, Wouter Bulten, MIT, https://github.com/wouterbulten/kalmanjs */
var KalmanFilter = (function () {
@ -173,6 +171,15 @@ var KalmanFilter = (function () {
var buf = Graphics.createArrayBuffer(240,160,2,{msb:true});
let LED = // LED as minimal and only definition (as instance / singleton)
{ isOn: false // status on / off, not needed if you don't need to ask for it
, set: function(v) { // turn on w/ no arg or truey, else off
g.setColor((this.isOn=(v===undefined||!!v))?1:0,0,0).fillCircle(40,10,10); }
, reset: function() { this.set(false); } // turn off
, write: function(v) { this.set(v); } // turn on w/ no arg or truey, else off
, toggle: function() { this.set( ! this.isOn); } // toggle the LED
}, LED1 = LED; // LED1 as 'synonym' for LED
// Load fonts
//require("Font7x11Numeric7Seg").add(Graphics);
@ -183,17 +190,16 @@ var canDraw = 1;
var time = ''; // Last time string displayed. Re displayed in background colour to remove before drawing new time.
var tmrLP; // Timer for delay in switching to low power after screen turns off
var max = {};
max.spd = 0;
max.alt = 0;
max.n = 0; // counter. Only start comparing for max after a certain number of fixes to allow kalman filter to have smoohed the data.
var maxSpd = 0;
var maxAlt = 0;
var maxN = 0; // counter. Only start comparing for max after a certain number of fixes to allow kalman filter to have smoohed the data.
var emulator = (process.env.BOARD=="EMSCRIPTEN")?1:0; // 1 = running in emulator. Supplies test values;
var wp = {}; // Waypoint to use for distance from cur position.
function nxtWp(inc){
cfg.wp+=inc;
function nxtWp(){
cfg.wp++;
loadWp();
}
@ -227,6 +233,7 @@ function drawScrn(dat) {
if (!canDraw) return;
buf.clear();
buf.setBgColor(0);
var n;
n = dat.val.toString();
@ -252,29 +259,21 @@ function drawScrn(dat) {
buf.setFontVector(35);
buf.drawString(dat.unit,5,164);
if ( dat.max ) drawMax(); // MAX display indicator
if ( dat.wp ) drawWP(); // Waypoint name
//Sats
if ( dat.sat ) {
if ( dat.age > 10 ) {
if ( dat.age > 90 ) dat.age = '>90';
drawSats('Age:'+dat.age);
}
else drawSats('Sats:'+dat.sats);
}
drawMax(dat.max); // MAX display indicator
drawWP(dat.wp); // Waypoint name
drawSats(dat.sats);
g.reset();
g.drawImage(img,0,40);
if ( pwrSav ) LED1.reset();
else LED1.set();
LED1.write(!pwrSav);
}
function drawPosn(dat) {
if (!canDraw) return;
buf.clear();
buf.setBgColor(0);
var x, y;
x=210;
@ -293,20 +292,12 @@ function drawPosn(dat) {
buf.drawString(dat.ew,x,y+70);
//Sats
if ( dat.sat ) {
if ( dat.age > 10 ) {
if ( dat.age > 90 ) dat.age = '>90';
drawSats('Age:'+dat.age);
}
else drawSats('Sats:'+dat.sats);
}
drawSats(dat.sats);
g.reset();
g.drawImage(img,0,40);
if ( pwrSav ) LED1.reset();
else LED1.set();
LED1.write(!pwrSav);
}
@ -314,6 +305,8 @@ function drawClock() {
if (!canDraw) return;
buf.clear();
buf.setBgColor(0);
var x, y;
x=185;
y=0;
@ -329,19 +322,14 @@ function drawClock() {
g.reset();
g.drawImage(img,0,40);
if ( pwrSav ) LED1.reset();
else LED1.set();
LED1.write(!pwrSav);
}
function drawWP() {
var nm = wp.name;
if ( nm == undefined || nm == 'NONE' || cfg.modeA ==1 ) nm = '';
buf.setColor(2);
function drawWP(wp) {
buf.setColor(3);
buf.setFontAlign(0,1); //left, bottom
buf.setFontVector(48);
buf.drawString(nm.substring(0,8),120,140);
buf.drawString(wp,120,140);
}
function drawSats(sats) {
@ -351,16 +339,15 @@ function drawSats(sats) {
buf.drawString(sats,240,160);
}
function drawMax() {
function drawMax(max) {
buf.setFontVector(30);
buf.setColor(2);
buf.setFontAlign(0,1); //centre, bottom
buf.drawString('MAX',120,164);
buf.drawString(max,120,164);
}
function onGPS(fix) {
if ( emulator ) {
if ( emulator ) {
fix.fix = 1;
fix.speed = 10 + (Math.random()*5);
fix.alt = 354 + (Math.random()*50);
@ -382,7 +369,12 @@ function onGPS(fix) {
var ns = '';
var ew = '';
var lon = '---.--';
var sats = '---';
// Waypoint name
var wpName = wp.name;
if ( wpName == undefined || wpName == 'NONE' ) wpName = '';
wpName = wpName.substring(0,8);
if (fix.fix) lf = fix;
@ -393,10 +385,9 @@ function onGPS(fix) {
if ( cfg.spdFilt ) lf.speed = spdFilter.filter(lf.speed);
if ( cfg.altFilt ) lf.alt = altFilter.filter(lf.alt);
lf.smoothed = 1;
if ( max.n <= 15 ) max.n++;
if ( maxN <= 15 ) maxN++;
}
// Speed
if ( cfg.spd == 0 ) {
m = require("locale").speed(lf.speed).match(/([0-9,\.]+)(.*)/); // regex splits numbers from units
@ -407,18 +398,19 @@ function onGPS(fix) {
if ( sp < 10 ) sp = sp.toFixed(1);
else sp = Math.round(sp);
if (isNaN(sp)) sp = '---';
if (parseFloat(sp) > parseFloat(max.spd) && max.n > 15 ) max.spd = sp;
if (parseFloat(sp) > parseFloat(maxSpd) && maxN > 15 ) maxSpd = sp;
// Altitude
al = lf.alt;
al = Math.round(parseFloat(al)/parseFloat(cfg.alt));
if (parseFloat(al) > parseFloat(max.alt) && max.n > 15 ) max.alt = al;
if (parseFloat(al) > parseFloat(maxAlt) && maxN > 15 ) maxAlt = al;
if (isNaN(al)) al = '---';
// Distance to waypoint
di = distance(lf,wp);
if (isNaN(di)) di = 0;
if (isNaN(di)) di = '--------';
// Age of last fix (secs)
age = Math.max(0,Math.round(getTime())-(lf.time.getTime()/1000));
@ -432,29 +424,34 @@ function onGPS(fix) {
if ( lf.lon < 0 ) ew = 'W';
lon = Math.abs(lf.lon.toFixed(2));
// Sats
if ( age > 10 ) {
sats = 'Age:'+Math.round(age);
if ( age > 90 ) sats = 'Age:>90';
}
else sats = 'Sats:'+lf.satellites;
}
if ( cfg.modeA == 0 ) {
// Speed
if ( showMax )
drawScrn({
val:max.spd,
val:maxSpd,
unit:cfg.spd_unit,
sats:lf.satellites,
sats:sats,
age:age,
max:true,
wp:false,
sat:true
max:'MAX',
wp:''
}); // Speed maximums
else
drawScrn({
val:sp,
unit:cfg.spd_unit,
sats:lf.satellites,
sats:sats,
age:age,
max:false,
wp:false,
sat:true
max:'SPD',
wp:''
});
}
@ -462,23 +459,21 @@ function onGPS(fix) {
// Alt
if ( showMax )
drawScrn({
val:max.alt,
val:maxAlt,
unit:cfg.alt_unit,
sats:lf.satellites,
sats:sats,
age:age,
max:true,
wp:false,
sat:true
max:'MAX',
wp:''
}); // Alt maximums
else
drawScrn({
val:al,
unit:cfg.alt_unit,
sats:lf.satellites,
sats:sats,
age:age,
max:false,
wp:false,
sat:true
max:'ALT',
wp:''
});
}
@ -487,24 +482,22 @@ function onGPS(fix) {
drawScrn({
val:di,
unit:cfg.dist_unit,
sats:lf.satellites,
sats:sats,
age:age,
max:false,
wp:true,
sat:true
max:'DST',
wp:wpName
});
}
if ( cfg.modeA == 3 ) {
// Position
drawPosn({
sats:lf.satellites,
drawPosn({
sats:sats,
age:age,
lat:lat,
lon:lon,
ns:ns,
ew:ew,
sat:true
ew:ew
});
}
@ -534,9 +527,9 @@ function nextFunc(dur) {
if ( cfg.modeA == 0 || cfg.modeA == 1 ) {
// Spd+Alt mode - Switch between fix and MAX
if ( dur < 2 ) showMax = !showMax; // Short press toggle fix/max display
else { max.spd = 0; max.alt = 0; } // Long press resets max values.
else { maxSpd = 0; maxAlt = 0; } // Long press resets max values.
}
else if ( cfg.modeA == 2) nxtWp(1); // Dist mode - Select next waypoint
else if ( cfg.modeA == 2) nxtWp(); // Dist mode - Select next waypoint
onGPS(lf);
}
@ -545,7 +538,7 @@ function updateClock() {
if (!canDraw) return;
if ( cfg.modeA != 4 ) return;
drawClock();
if ( emulator ) {max.spd++;max.alt++;}
if ( emulator ) {maxSpd++;maxAlt++;}
}
function startDraw(){
@ -585,7 +578,6 @@ function setButtons(){
setWatch(function(e){
pwrSav=!pwrSav;
if ( pwrSav ) {
LED1.reset();
var s = require('Storage').readJSON('setting.json',1)||{};
var t = s.timeout||10;
Bangle.setLCDTimeout(t);
@ -593,8 +585,8 @@ function setButtons(){
else {
Bangle.setLCDTimeout(0);
// Bangle.setLCDPower(1);
LED1.set();
}
LED1.write(!pwrSav);
}, BTN2, {repeat:true,edge:"falling"});
// BTN3 - next screen
@ -690,7 +682,8 @@ var img = {
};
if ( cfg.colour == 1 ) img.palette = new Uint16Array([0,0xFFFF,0xFFF6,0xDFFF]);
if ( cfg.colour == 2 ) img.palette = new Uint16Array([0,0xFF800,0xFAE0,0xF813]);
if ( cfg.colour == 2 ) img.palette = new Uint16Array([0,0xF800,0xFAE0,0xF813]);
if ( cfg.colour == 3 ) img.palette = new Uint16Array([0xFFFF,0x007F,0x0054,0x0054]);
var SCREENACCESS = {
withApp:true,

View File

@ -65,7 +65,8 @@
'< Back': function() { E.showMenu(appMenu); },
'Default' : function() { setColour(0); },
'Hi Contrast' : function() { setColour(1); },
'Night' : function() { setColour(2); }
'Night' : function() { setColour(2); },
'Inverted' : function() { setColour(3); }
};
const kalMenu = {

View File

@ -31,3 +31,6 @@ Which one is which ?
![](A.jpg)
![](B.jpg)
Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/)

View File

@ -19,3 +19,4 @@
Stop goal drawing outside widget area
Fix issue with widget overwrite in large font mode
Memory usage enhancements
0.20: Fix issue where step count would randomly reset

View File

@ -53,7 +53,7 @@
E.on('kill', () => {
if (!settings) { loadSettings() }
let d = {
lastUpdate : lastUpdate.toISOString(),
lastUpdate : lastUpdate.valueOf(),
stepsToday : stp_today,
settings : settings,
};

2
core

@ -1 +1 @@
Subproject commit 2a8e872ecb143a10e53273b4d3473164e104e1d3
Subproject commit b033af017f6789a6a7777e6ef1428d94995a9b8b