Merge branch 'master' into widalarmeta-hidden
commit
d1eb54a52a
|
|
@ -1 +1,2 @@
|
||||||
0.01: First version
|
0.01: First version
|
||||||
|
0.02: Support BangleJS2
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
(() => {
|
(() => {
|
||||||
|
const pin = process.env.HWVERSION === 2 ? D3 : D30;
|
||||||
|
|
||||||
var id;
|
var id;
|
||||||
Bangle.on('charging', (charging) => {
|
Bangle.on('charging', (charging) => {
|
||||||
if (charging) {
|
if (charging) {
|
||||||
|
|
@ -6,9 +8,9 @@
|
||||||
var max = 0;
|
var max = 0;
|
||||||
var count = 0;
|
var count = 0;
|
||||||
id = setInterval(() => {
|
id = setInterval(() => {
|
||||||
var d30 = analogRead(D30);
|
var battlvl = analogRead(pin);
|
||||||
if (max < d30) {
|
if (max < battlvl) {
|
||||||
max = d30;
|
max = battlvl;
|
||||||
count = 0;
|
count = 0;
|
||||||
} else {
|
} else {
|
||||||
count++;
|
count++;
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
(function(){var a;Bangle.on("charging",function(e){if(e){if(!a){var c=0,b=0;a=setInterval(function(){var d=analogRead(D30);c<d?(c=d,b=0):(b++,10<=b&&(Bangle.buzz(500),setTimeout(function(){return Bangle.buzz(500)},1E3)))},3E4)}}else a&&(clearInterval(a),a=void 0)})})()
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
{ "id": "chargent",
|
{ "id": "chargent",
|
||||||
"name": "Charge Gently",
|
"name": "Charge Gently",
|
||||||
"version": "0.01",
|
"version": "0.02",
|
||||||
"description": "When charging, reminds you to disconnect the watch to prolong battery life.",
|
"description": "When charging, reminds you to disconnect the watch to prolong battery life.",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
"type": "bootloader",
|
"type": "bootloader",
|
||||||
"tags": "battery",
|
"tags": "battery",
|
||||||
"supports": ["BANGLEJS"],
|
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name": "chargent.boot.js", "url": "boot.min.js"}
|
{"name": "chargent.boot.js", "url": "boot.js"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New app!
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Happy Clock
|
||||||
|
|
||||||
|
A happy clock.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## How to read this happy clock?
|
||||||
|
- The left eye shows the hour, the right hour the minutes.
|
||||||
|
- The happiness decreases as the battery level decreases.
|
||||||
|
- The left mouthline shows whether your bangle is locked or not
|
||||||
|
- The right mouthline whether you reached 10k steps or not.
|
||||||
|
|
||||||
|
Here you can see an example of a locked bangle with a low battery:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Creator
|
||||||
|
- [David Peer](https://github.com/peerdavid).
|
||||||
|
|
||||||
|
Thanks for this great idea:
|
||||||
|
http://apps.rebble.io/de_DE/application/55014a037ed24ae745000004?section=watchfaces
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
/************************************************
|
||||||
|
* Happy Clock
|
||||||
|
*/
|
||||||
|
var W = g.getWidth(),R=W/2;
|
||||||
|
var H = g.getHeight();
|
||||||
|
var drawTimeout;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HELPER
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Based on the great multi clock from https://github.com/jeffmer/BangleApps/
|
||||||
|
Graphics.prototype.drawPupils = function(cx, cy, r1, dx, dy, angle) {
|
||||||
|
angle = angle % 360;
|
||||||
|
var theta=angle*Math.PI/180;
|
||||||
|
var x = parseInt(cx+r1*Math.sin(theta)*1.2);
|
||||||
|
var y = parseInt(cy-r1*Math.cos(theta)*1.2);
|
||||||
|
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
g.fillCircle(cx, cy, 32);
|
||||||
|
g.setColor(g.theme.bg);
|
||||||
|
g.fillCircle(cx, cy, 27);
|
||||||
|
g.fillCircle(cx+dx, cy+dy, 28);
|
||||||
|
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
g.fillCircle(x, y, 8);
|
||||||
|
g.fillCircle(x+1, y, 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
let quadraticCurve = function(t, p0x, p0y, p1x, p1y, p2x, p2y){
|
||||||
|
var t2 = t * t;
|
||||||
|
var oneMinT = 1 - t;
|
||||||
|
var oneMinT2 = oneMinT * oneMinT;
|
||||||
|
return {
|
||||||
|
x: p0x * oneMinT2 + 2 * p1x * t * oneMinT + p2x *t2,
|
||||||
|
y: p0y * oneMinT2 + 2 * p1y * t * oneMinT + p2y *t2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thanks to user stephaneAG from the Espruino forum!
|
||||||
|
// https://forum.espruino.com/conversations/330154/#comment14593349
|
||||||
|
let drawCurve = function(x1, y1, x2, y2, x3, y3){
|
||||||
|
var p0 = { x: x1, y: y1};
|
||||||
|
var p1 = { x: x2, y: y2};
|
||||||
|
var p2 = { x: x3, y: y3};
|
||||||
|
var time = 0;
|
||||||
|
var stepping = 0.1; // Stepping defines the speed.
|
||||||
|
|
||||||
|
for(var y = 0; y < 8; y++){
|
||||||
|
var pathPts = [];
|
||||||
|
for(time = 0; time <= 1; time+= stepping){
|
||||||
|
var pos = quadraticCurve(time, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y);
|
||||||
|
pathPts.push(pos.x, pos.y+y);
|
||||||
|
}
|
||||||
|
g.drawPoly(pathPts, false);
|
||||||
|
}
|
||||||
|
g.flip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draw the clock
|
||||||
|
*/
|
||||||
|
let drawEyes = function(){
|
||||||
|
// And now the analog time
|
||||||
|
var drawHour = g.drawPupils.bind(g,55,70,12,1,0);
|
||||||
|
var drawMinute = g.drawPupils.bind(g,125,70,12,0,1);
|
||||||
|
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
|
||||||
|
// Compute angles
|
||||||
|
var date = new Date();
|
||||||
|
var m = parseInt(date.getMinutes() * 360 / 60);
|
||||||
|
var h = date.getHours();
|
||||||
|
h = h > 12 ? h-12 : h;
|
||||||
|
h += date.getMinutes()/60.0;
|
||||||
|
h = parseInt(h*360/12);
|
||||||
|
|
||||||
|
// Draw minute and hour fg
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
drawHour(h);
|
||||||
|
drawMinute(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let drawSmile = function(isLocked){
|
||||||
|
var y = 120;
|
||||||
|
var o = parseInt(E.getBattery()*0.8);
|
||||||
|
|
||||||
|
// Draw smile
|
||||||
|
drawCurve(30, y, W/2+12, y+o, W-40, y);
|
||||||
|
|
||||||
|
// And the two "mouth lines"
|
||||||
|
var reachedSteps = Bangle.getHealthStatus("day").steps >= 10000;
|
||||||
|
for(var i=0; i < 6; i++){
|
||||||
|
if(isLocked) g.drawLine(25, y+6+i, 35, y-5+i);
|
||||||
|
if(reachedSteps) g.drawLine(W-35, y+5+i, W-45, y-5+i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let drawEyeBrow = function(){
|
||||||
|
var w = 6;
|
||||||
|
for(var i = 0; i < w; i++){
|
||||||
|
g.drawLine(25, 25+i, 70, 15+i%3);
|
||||||
|
g.drawLine(W-25, 28+i%3, W-68, 19+i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let draw = function(){
|
||||||
|
// Queue draw in one minute
|
||||||
|
queueDraw();
|
||||||
|
|
||||||
|
var isLocked = Bangle.isLocked();
|
||||||
|
drawHelper(isLocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
let drawHelper = function(isLocked){
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
g.reset().clear();
|
||||||
|
|
||||||
|
drawEyes();
|
||||||
|
drawEyeBrow();
|
||||||
|
drawSmile(isLocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Listeners
|
||||||
|
*/
|
||||||
|
Bangle.on('lcdPower',on=>{
|
||||||
|
if (on) {
|
||||||
|
draw();
|
||||||
|
} else { // stop draw timer
|
||||||
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
|
drawTimeout = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Bangle.on('lock', function(isLocked) {
|
||||||
|
draw(isLocked);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some helpers
|
||||||
|
*/
|
||||||
|
let queueDraw = function() {
|
||||||
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
|
drawTimeout = setTimeout(function() {
|
||||||
|
drawTimeout = undefined;
|
||||||
|
draw();
|
||||||
|
}, 60000 - (Date.now() % 60000));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lets start widgets, listen for btn etc.
|
||||||
|
*/
|
||||||
|
// Show launcher when middle button pressed
|
||||||
|
Bangle.setUI("clock");
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
require('widget_utils').hide();
|
||||||
|
|
||||||
|
// Clear the screen once, at startup and draw clock
|
||||||
|
// g.setTheme({bg:"#fff",fg:"#000",dark:false});
|
||||||
|
draw();
|
||||||
|
|
||||||
|
// After drawing the watch face, we can draw the widgets
|
||||||
|
// Bangle.drawWidgets();
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwgP/ADEP/AEC+E//kH//+gYIB8F//1/B4U/ERgdB/wdB//AFIJGCx/n+P8EIM/+fnE4IBB/PAv4aBv/84E/z/8//8wAFDwwFB74FBgQFD/wFGyF/AoUAz//z/+AoPfAoV/gPP/+/IIP585lCj/z8ZvCw+H/HwPQUf/iACACIrBAAaRCGAP+AoXzAonxAoJRB//lAQJLBC4X/44IE8KeCVoQCBj4CB/iYBEwX+h6sCAAOB8BCD4C+CDwTKCACI="))
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 469 B |
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"id": "happyclk",
|
||||||
|
"name": "Happy Clock",
|
||||||
|
"shortName":"Happy Clock",
|
||||||
|
"icon": "happyclk.png",
|
||||||
|
"version":"0.01",
|
||||||
|
"readme": "README.md",
|
||||||
|
"supports": ["BANGLEJS2"],
|
||||||
|
"description": "A happy clock :)",
|
||||||
|
"type": "clock",
|
||||||
|
"tags": "clock",
|
||||||
|
"screenshots": [
|
||||||
|
{"url":"screenshot_1.png"},
|
||||||
|
{"url":"screenshot_2.png"},
|
||||||
|
{"url":"screenshot_3.png"}
|
||||||
|
],
|
||||||
|
"storage": [
|
||||||
|
{"name":"happyclk.app.js","url":"happyclk.app.js"},
|
||||||
|
{"name":"happyclk.img","url":"happyclk.icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
|
|
@ -9,6 +9,7 @@
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"description": "Simple and slim battery widget with charge status and percentage",
|
"description": "Simple and slim battery widget with charge status and percentage",
|
||||||
"tags": "widget,battery",
|
"tags": "widget,battery",
|
||||||
|
"provides_widgets" : ["battery"],
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"hwid_a_battery_widget.wid.js","url":"widget.js"}
|
{"name":"hwid_a_battery_widget.wid.js","url":"widget.js"}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,3 @@ This launcher shows 9 apps per screen, making it much faster to navigate versus
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
## Technical note
|
|
||||||
|
|
||||||
The app uses `E.showScroller`'s code in the app but not the function itself because `E.showScroller` doesn't report the position of a press to the select function.
|
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,14 @@
|
||||||
}) };
|
}) };
|
||||||
s.writeJSON("iconlaunch.cache.json", launchCache);
|
s.writeJSON("iconlaunch.cache.json", launchCache);
|
||||||
}
|
}
|
||||||
let scroll = 0;
|
|
||||||
let selectedItem = -1;
|
let selectedItem = -1;
|
||||||
const R = Bangle.appRect;
|
const R = Bangle.appRect;
|
||||||
const iconSize = 48;
|
const iconSize = 48;
|
||||||
const appsN = Math.floor(R.w / iconSize);
|
const appsN = Math.floor(R.w / iconSize);
|
||||||
const whitespace = (R.w - appsN * iconSize) / (appsN + 1);
|
const whitespace = (R.w - appsN * iconSize) / (appsN + 1);
|
||||||
const itemSize = iconSize + whitespace;
|
const itemSize = iconSize + whitespace;
|
||||||
|
|
||||||
let drawItem = function(itemI, r) {
|
let drawItem = function(itemI, r) {
|
||||||
g.clearRect(r.x, r.y, r.x + r.w - 1, r.y + r.h - 1);
|
g.clearRect(r.x, r.y, r.x + r.w - 1, r.y + r.h - 1);
|
||||||
let x = 0;
|
let x = 0;
|
||||||
|
|
@ -61,36 +62,26 @@
|
||||||
}
|
}
|
||||||
x += iconSize;
|
x += iconSize;
|
||||||
}
|
}
|
||||||
drawText(itemI);
|
drawText(itemI, r.y);
|
||||||
};
|
};
|
||||||
let drawItemAuto = function(i) {
|
|
||||||
let y = idxToY(i);
|
let drawText = function(i, appY) {
|
||||||
g.reset().setClipRect(R.x, y, R.x2, y + itemSize);
|
|
||||||
drawItem(i, {
|
|
||||||
x: R.x,
|
|
||||||
y: y,
|
|
||||||
w: R.w,
|
|
||||||
h: itemSize
|
|
||||||
});
|
|
||||||
g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1);
|
|
||||||
};
|
|
||||||
let lastIsDown = false;
|
|
||||||
let drawText = function(i) {
|
|
||||||
const selectedApp = launchCache.apps[selectedItem];
|
const selectedApp = launchCache.apps[selectedItem];
|
||||||
const idy = (selectedItem - (selectedItem % 3)) / 3;
|
const idy = (selectedItem - (selectedItem % 3)) / 3;
|
||||||
if (!selectedApp || i != idy) return;
|
if (!selectedApp || i != idy) return;
|
||||||
const appY = idxToY(idy) + iconSize / 2;
|
appY = appY + itemSize/2;
|
||||||
g.setFontAlign(0, 0, 0);
|
g.setFontAlign(0, 0, 0);
|
||||||
g.setFont("12x20");
|
g.setFont("12x20");
|
||||||
const rect = g.stringMetrics(selectedApp.name);
|
const rect = g.stringMetrics(selectedApp.name);
|
||||||
g.clearRect(
|
g.clearRect(
|
||||||
R.w / 2 - rect.width / 2,
|
R.w / 2 - rect.width / 2 - 2,
|
||||||
appY - rect.height / 2,
|
appY - rect.height / 2 - 2,
|
||||||
R.w / 2 + rect.width / 2,
|
R.w / 2 + rect.width / 2 + 1,
|
||||||
appY + rect.height / 2
|
appY + rect.height / 2 + 1
|
||||||
);
|
);
|
||||||
g.drawString(selectedApp.name, R.w / 2, appY);
|
g.drawString(selectedApp.name, R.w / 2, appY);
|
||||||
};
|
};
|
||||||
|
|
||||||
let selectItem = function(id, e) {
|
let selectItem = function(id, e) {
|
||||||
const iconN = E.clip(Math.floor((e.x - R.x) / itemSize), 0, appsN - 1);
|
const iconN = E.clip(Math.floor((e.x - R.x) / itemSize), 0, appsN - 1);
|
||||||
const appId = id * appsN + iconN;
|
const appId = id * appsN + iconN;
|
||||||
|
|
@ -108,96 +99,32 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectedItem = appId;
|
selectedItem = appId;
|
||||||
drawItems();
|
if (scroller) scroller.draw();
|
||||||
};
|
};
|
||||||
let idxToY = function(i) {
|
|
||||||
return i * itemSize + R.y - (scroll & ~1);
|
|
||||||
};
|
|
||||||
let YtoIdx = function(y) {
|
|
||||||
return Math.floor((y + (scroll & ~1) - R.y) / itemSize);
|
|
||||||
};
|
|
||||||
let drawItems = function() {
|
|
||||||
g.reset().clearRect(R.x, R.y, R.x2, R.y2);
|
|
||||||
g.setClipRect(R.x, R.y, R.x2, R.y2);
|
|
||||||
let a = YtoIdx(R.y);
|
|
||||||
let b = Math.min(YtoIdx(R.y2), 99);
|
|
||||||
for (let i = a; i <= b; i++)
|
|
||||||
drawItem(i, {
|
|
||||||
x: R.x,
|
|
||||||
y: idxToY(i),
|
|
||||||
w: R.w,
|
|
||||||
h: itemSize,
|
|
||||||
});
|
|
||||||
g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1);
|
|
||||||
};
|
|
||||||
drawItems();
|
|
||||||
g.flip();
|
|
||||||
const itemsN = Math.ceil(launchCache.apps.length / appsN);
|
const itemsN = Math.ceil(launchCache.apps.length / appsN);
|
||||||
let onDrag = function(e) {
|
|
||||||
updateTimeout();
|
let back = ()=>{};
|
||||||
g.setColor(g.theme.fg);
|
if (settings.oneClickExit) back = Bangle.showClock;
|
||||||
g.setBgColor(g.theme.bg);
|
|
||||||
let dy = e.dy;
|
let options = {
|
||||||
if (scroll + R.h - dy > itemsN * itemSize) {
|
h: itemSize,
|
||||||
dy = scroll + R.h - itemsN * itemSize;
|
c: itemsN,
|
||||||
}
|
draw: drawItem,
|
||||||
if (scroll - dy < 0) {
|
select: selectItem,
|
||||||
dy = scroll;
|
back: back,
|
||||||
}
|
|
||||||
scroll -= dy;
|
|
||||||
scroll = E.clip(scroll, 0, itemSize * (itemsN - 1));
|
|
||||||
g.setClipRect(R.x, R.y, R.x2, R.y2);
|
|
||||||
g.scroll(0, dy);
|
|
||||||
if (dy < 0) {
|
|
||||||
g.setClipRect(R.x, R.y2 - (1 - dy), R.x2, R.y2);
|
|
||||||
let i = YtoIdx(R.y2 - (1 - dy));
|
|
||||||
let y = idxToY(i);
|
|
||||||
while (y < R.y2) {
|
|
||||||
drawItem(i, {
|
|
||||||
x: R.x,
|
|
||||||
y: y,
|
|
||||||
w: R.w,
|
|
||||||
h: itemSize,
|
|
||||||
});
|
|
||||||
i++;
|
|
||||||
y += itemSize;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g.setClipRect(R.x, R.y, R.x2, R.y + dy);
|
|
||||||
let i = YtoIdx(R.y + dy);
|
|
||||||
let y = idxToY(i);
|
|
||||||
while (y > R.y - itemSize) {
|
|
||||||
drawItem(i, {
|
|
||||||
x: R.x,
|
|
||||||
y: y,
|
|
||||||
w: R.w,
|
|
||||||
h: itemSize,
|
|
||||||
});
|
|
||||||
y -= itemSize;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1);
|
|
||||||
};
|
|
||||||
let mode = {
|
|
||||||
mode: "custom",
|
|
||||||
drag: onDrag,
|
|
||||||
touch: (_, e) => {
|
|
||||||
if (e.y < R.y - 4) return;
|
|
||||||
updateTimeout();
|
|
||||||
let i = YtoIdx(e.y);
|
|
||||||
selectItem(i, e);
|
|
||||||
},
|
|
||||||
swipe: (h,_) => { if(settings.swipeExit && h==1) { Bangle.showClock(); } },
|
|
||||||
btn: _=> { if (settings.oneClickExit) Bangle.showClock(); },
|
|
||||||
remove: function() {
|
remove: function() {
|
||||||
if (timeout) clearTimeout(timeout);
|
if (timeout) clearTimeout(timeout);
|
||||||
|
Bangle.removeListener("drag", updateTimeout);
|
||||||
|
Bangle.removeListener("touch", updateTimeout);
|
||||||
|
Bangle.removeListener("swipe", swipeHandler);
|
||||||
if (settings.fullscreen) { // for fast-load, if we hid widgets then we should show them again
|
if (settings.fullscreen) { // for fast-load, if we hid widgets then we should show them again
|
||||||
require("widget_utils").show();
|
require("widget_utils").show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let scroller = E.showScroller(options);
|
||||||
|
|
||||||
let timeout;
|
let timeout;
|
||||||
const updateTimeout = function(){
|
const updateTimeout = function(){
|
||||||
if (settings.timeOut!="Off"){
|
if (settings.timeOut!="Off"){
|
||||||
|
|
@ -207,7 +134,11 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
updateTimeout();
|
let swipeHandler = (h,_) => { if(settings.swipeExit && h==1) { Bangle.showClock(); } };
|
||||||
|
|
||||||
Bangle.setUI(mode);
|
Bangle.on("swipe", swipeHandler)
|
||||||
|
Bangle.on("drag", updateTimeout);
|
||||||
|
Bangle.on("touch", updateTimeout);
|
||||||
|
|
||||||
|
updateTimeout();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,9 @@ All touch and drag inputs related to this widget are cached/masked to prevent ac
|
||||||
Change the maximum delay between first touch and re-touch/drag to change the brightness or disable changing the brightness completely.
|
Change the maximum delay between first touch and re-touch/drag to change the brightness or disable changing the brightness completely.
|
||||||
* __Min Value__
|
* __Min Value__
|
||||||
_1%_ / _2%_ / _..._ / __10%__ / _..._ / _100%_
|
_1%_ / _2%_ / _..._ / __10%__ / _..._ / _100%_
|
||||||
Set the minimal level of brightness you can change to.
|
Set the minimal level of brightness you can change to.
|
||||||
|
* __Tap to lock__
|
||||||
|
Tapping the widget locks the screen, rather than toggling brightness.
|
||||||
|
|
||||||
#### Unlock - Set double tap side to unlock:
|
#### Unlock - Set double tap side to unlock:
|
||||||
* __TapSide__
|
* __TapSide__
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
oversize: 20,
|
oversize: 20,
|
||||||
dragDelay: 500,
|
dragDelay: 500,
|
||||||
minValue: 0.1,
|
minValue: 0.1,
|
||||||
|
tapToLock: false,
|
||||||
unlockSide: "",
|
unlockSide: "",
|
||||||
tapSide: "right",
|
tapSide: "right",
|
||||||
tapOn: "always",
|
tapOn: "always",
|
||||||
|
|
@ -119,6 +120,11 @@
|
||||||
max: 100,
|
max: 100,
|
||||||
step: 1
|
step: 1
|
||||||
},
|
},
|
||||||
|
tapToLock: {
|
||||||
|
title: ["on", "off"],
|
||||||
|
value: [true, false],
|
||||||
|
drawWidgets: false
|
||||||
|
},
|
||||||
unlockSide: {
|
unlockSide: {
|
||||||
title: ["off", "left", "right", "top", "bottom", "front", "back"],
|
title: ["off", "left", "right", "top", "bottom", "front", "back"],
|
||||||
value: ["", "left", "right", "top", "bottom", "front", "back"]
|
value: ["", "left", "right", "top", "bottom", "front", "back"]
|
||||||
|
|
@ -154,6 +160,7 @@
|
||||||
"Oversize": getEntry("oversize"),
|
"Oversize": getEntry("oversize"),
|
||||||
"Drag Delay": getEntry("dragDelay"),
|
"Drag Delay": getEntry("dragDelay"),
|
||||||
"Min Value": getEntry("minValue"),
|
"Min Value": getEntry("minValue"),
|
||||||
|
"Tap to lock": getEntry("tapToLock"),
|
||||||
"-- Unlock": 0,
|
"-- Unlock": 0,
|
||||||
"TapSide": getEntry("unlockSide"),
|
"TapSide": getEntry("unlockSide"),
|
||||||
"-- Flash": 0,
|
"-- Flash": 0,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
oversize: 20,
|
oversize: 20,
|
||||||
dragDelay: 500,
|
dragDelay: 500,
|
||||||
minValue: 0.1,
|
minValue: 0.1,
|
||||||
|
tapToLock: false,
|
||||||
unlockSide: "",
|
unlockSide: "",
|
||||||
tapSide: "right",
|
tapSide: "right",
|
||||||
tapOn: "always",
|
tapOn: "always",
|
||||||
|
|
@ -208,8 +209,12 @@
|
||||||
w.dragStatus = "off";
|
w.dragStatus = "off";
|
||||||
}, w.dragDelay, w);
|
}, w.dragDelay, w);
|
||||||
}
|
}
|
||||||
// switch backlight
|
if (w.tapToLock) {
|
||||||
w.changeValue();
|
Bangle.setLocked(true);
|
||||||
|
} else {
|
||||||
|
// switch backlight
|
||||||
|
w.changeValue();
|
||||||
|
}
|
||||||
// masks this touch event by messing up the event handler
|
// masks this touch event by messing up the event handler
|
||||||
// see https://github.com/espruino/Espruino/issues/2151
|
// see https://github.com/espruino/Espruino/issues/2151
|
||||||
Bangle.removeListener("touch", w.touchListener);
|
Bangle.removeListener("touch", w.touchListener);
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,4 @@
|
||||||
0.10: Fix: Do not wake when falling asleep
|
0.10: Fix: Do not wake when falling asleep
|
||||||
0.11: Minor tweaks
|
0.11: Minor tweaks
|
||||||
0.12: Support javascript command to execute as defined in scheduler 'js' configuration
|
0.12: Support javascript command to execute as defined in scheduler 'js' configuration
|
||||||
|
0.13: Fix dated events alarm on wrong date
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ const config = Object.assign({
|
||||||
disableAlarm: false,
|
disableAlarm: false,
|
||||||
}
|
}
|
||||||
}, require("Storage").readJSON(CONFIGFILE,1) || {});
|
}, require("Storage").readJSON(CONFIGFILE,1) || {});
|
||||||
const active = alarms.filter(a=>a.on);
|
const active = alarms.filter(alarm => require("sched").getTimeToAlarm(alarm));
|
||||||
const schedSettings = require("sched").getSettings();
|
const schedSettings = require("sched").getSettings();
|
||||||
let buzzCount = schedSettings.buzzCount;
|
let buzzCount = schedSettings.buzzCount;
|
||||||
let logs = [];
|
let logs = [];
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "sleepphasealarm",
|
"id": "sleepphasealarm",
|
||||||
"name": "SleepPhaseAlarm",
|
"name": "SleepPhaseAlarm",
|
||||||
"shortName": "SleepPhaseAlarm",
|
"shortName": "SleepPhaseAlarm",
|
||||||
"version": "0.12",
|
"version": "0.13",
|
||||||
"description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.",
|
"description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "alarm",
|
"tags": "alarm",
|
||||||
|
|
@ -14,6 +14,6 @@
|
||||||
{"name":"sleepphasealarm.settings.js","url":"settings.js"},
|
{"name":"sleepphasealarm.settings.js","url":"settings.js"},
|
||||||
{"name":"sleepphasealarm.img","url":"app-icon.js","evaluate":true}
|
{"name":"sleepphasealarm.img","url":"app-icon.js","evaluate":true}
|
||||||
],
|
],
|
||||||
"data": [{"name":"sleepphasealarm.json","storageFile":true}],
|
"data": [{"name":"sleepphasealarm.json"}],
|
||||||
"interface": "interface.html"
|
"interface": "interface.html"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,4 @@
|
||||||
0.07: Use ClockFace module and rework the settings to be able to personnalize the order of the lines
|
0.07: Use ClockFace module and rework the settings to be able to personnalize the order of the lines
|
||||||
0.08: Hide widgets instead of not loading them at all
|
0.08: Hide widgets instead of not loading them at all
|
||||||
Use Clockface_menu for widgets and power saving settings
|
Use Clockface_menu for widgets and power saving settings
|
||||||
|
0.09: Add default HRM value, default altitude value
|
||||||
|
|
|
||||||
|
|
@ -1,211 +1,239 @@
|
||||||
const locale = require("locale");
|
{
|
||||||
var heartRate = 0;
|
const locale = require("locale");
|
||||||
var altitude = -9001;
|
let heartRate = 0;
|
||||||
|
let altitude = -9001;
|
||||||
|
|
||||||
const fontColor = g.theme.dark ? "#0f0" : "#000";
|
const fontColor = g.theme.dark ? "#0f0" : "#000";
|
||||||
// handling the differents versions of the Banglejs smartwatch screen sizes
|
// handling the differents versions of the Banglejs smartwatch screen sizes
|
||||||
if (process.env.HWVERSION == 1){
|
// default BJS2
|
||||||
var paddingY = 3;
|
let paddingY = 2;
|
||||||
var font6x8At4Size = 48;
|
let font6x8At4Size = 32;
|
||||||
var font6x8At2Size = 27;
|
let font6x8At2Size = 18;
|
||||||
var font6x8FirstTextSize = 6;
|
let font6x8FirstTextSize = 4;
|
||||||
var font6x8DefaultTextSize = 3;
|
let font6x8DefaultTextSize = 2;
|
||||||
} else{
|
if (process.env.HWVERSION == 1){
|
||||||
var paddingY = 2;
|
paddingY = 3;
|
||||||
var font6x8At4Size = 32;
|
font6x8At4Size = 48;
|
||||||
var font6x8At2Size = 18;
|
font6x8At2Size = 27;
|
||||||
var font6x8FirstTextSize = 4;
|
font6x8FirstTextSize = 6;
|
||||||
var font6x8DefaultTextSize = 2;
|
font6x8DefaultTextSize = 3;
|
||||||
}
|
}
|
||||||
|
// initialising the clockface
|
||||||
|
const ClockFace = require("ClockFace");
|
||||||
|
const clock = new ClockFace({
|
||||||
|
precision: 60,
|
||||||
|
settingsFile: "terminalclock.json",
|
||||||
|
|
||||||
// initialising the clockface
|
init: function () {
|
||||||
const ClockFace = require("ClockFace");
|
// check settings and set default if needed
|
||||||
const clock = new ClockFace({
|
this.showHRM = false;
|
||||||
precision: 60,
|
this.showAltitude = false;
|
||||||
settingsFile: "terminalclock.json",
|
this.lock_precision = this.precision;
|
||||||
|
this.unlock_precision = 1;
|
||||||
|
if (this.HRMinConfidence === undefined) this.HRMinConfidence = 50;
|
||||||
|
if (this.PowerOnInterval === undefined) this.PowerOnInterval = 15;
|
||||||
|
if (this.powerSave===undefined) this.powerSave = this.powerSaving; // migrate old setting
|
||||||
|
if (this.powerSave===undefined) this.powerSave = true;
|
||||||
|
|
||||||
init: function () {
|
["L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9"].forEach(k => {
|
||||||
// check settings and set default if needed
|
if (this[k]===undefined){
|
||||||
this.showHRM = false;
|
if(k == "L2") this[k] = "Date";
|
||||||
this.showAltitude = false;
|
else if(k == "L3") {
|
||||||
this.lock_precision = this.precision;
|
this[k] = "HR";
|
||||||
this.unlock_precision = 1;
|
this.showHRM = true;
|
||||||
if (this.HRMinConfidence === undefined) this.HRMinConfidence = 50;
|
}else if(k == "L4") this[k] = "Motion";
|
||||||
if (this.PowerOnInterval === undefined) this.PowerOnInterval = 15;
|
else if(k == "L5") this[k] = "Steps";
|
||||||
if (this.powerSave===undefined) this.powerSave = this.powerSaving; // migrate old setting
|
else if(k == "L6") this[k] = ">";
|
||||||
if (this.powerSave===undefined) this.powerSave = true;
|
else this[k] = "Empty";
|
||||||
["L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9"].forEach(k => {
|
}
|
||||||
if (this[k]===undefined){
|
else if (this[k]==="HR") this.showHRM = true;
|
||||||
if(k == "L2") this[k] = "Date";
|
else if (this[k]==="Alt") this.showAltitude = true && process.env.HWVERSION == 2;
|
||||||
else if(k == "L3") {
|
});
|
||||||
this[k] = "HR";
|
|
||||||
this.showHRM = true;
|
// set the services (HRM, pressure sensor, etc....)
|
||||||
}else if(k == "L4") this[k] = "Motion";
|
if(!this.powerSave){
|
||||||
else if(k == "L5") this[k] = "Steps";
|
turnOnServices();
|
||||||
else if(k == "L6") this[k] = ">";
|
} else{
|
||||||
else this[k] = "Empty";
|
this.turnOnInterval = setInterval(turnOnServices, this.PowerOnInterval*60000); // every PowerOnInterval min
|
||||||
}
|
}
|
||||||
else if (this[k]==="HR") this.showHRM = true;
|
// start the clock unlocked
|
||||||
else if (this[k]==="Alt") this.showAltitude = true && process.env.HWVERSION == 2;
|
unlock();
|
||||||
});
|
},
|
||||||
|
|
||||||
// set the lock and unlock actions
|
draw: function (date) {
|
||||||
Bangle.on("lock", on => {
|
let curPos = 1;
|
||||||
if (on) lock();
|
g.setFontAlign(-1, -1);
|
||||||
else unlock();
|
g.setColor(fontColor);
|
||||||
});
|
drawTime(date, curPos);
|
||||||
|
|
||||||
// set the services (HRM, pressure sensor, etc....)
|
|
||||||
if(!this.powerSave){
|
|
||||||
turnOnServices();
|
|
||||||
} else{
|
|
||||||
setInterval(turnOnServices, this.PowerOnInterval*60000); // every PowerOnInterval min
|
|
||||||
}
|
|
||||||
// start the clock unlocked
|
|
||||||
unlock();
|
|
||||||
},
|
|
||||||
|
|
||||||
draw: function (date) {
|
|
||||||
var curPos = 1;
|
|
||||||
g.setFontAlign(-1, -1);
|
|
||||||
g.setColor(fontColor);
|
|
||||||
drawTime(date, curPos);
|
|
||||||
curPos++;
|
|
||||||
|
|
||||||
["L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9"].forEach(line => {
|
|
||||||
if (this[line]==='Date') drawDate(date, curPos);
|
|
||||||
else if (this[line]==='HR') drawHRM(curPos);
|
|
||||||
else if (this[line]==='Motion') drawMotion(curPos);
|
|
||||||
else if (this[line]==='Alt') drawAltitude(curPos);
|
|
||||||
else if (this[line]==='Steps') drawStepCount(curPos);
|
|
||||||
else if (this[line]==='>') drawInput(curPos);
|
|
||||||
curPos++;
|
curPos++;
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
["L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9"].forEach(line => {
|
||||||
|
if (this[line]==='Date') drawDate(date, curPos);
|
||||||
|
else if (this[line]==='HR') drawHRM(curPos);
|
||||||
|
else if (this[line]==='Motion') drawMotion(curPos);
|
||||||
|
else if (this[line]==='Alt') drawAltitude(curPos);
|
||||||
|
else if (this[line]==='Steps') drawStepCount(curPos);
|
||||||
|
else if (this[line]==='>') drawInput(curPos);
|
||||||
|
curPos++;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/* ----------------------------
|
/*
|
||||||
Draw related of specific lines
|
// todo add fastloading when the memory leak is fixed
|
||||||
-------------------------------- */
|
remove: function() {
|
||||||
|
if (this.turnOnInterval){
|
||||||
function drawLine(line, pos){
|
clearInterval(this.turnOnInterval);
|
||||||
if(pos == 1)
|
delete this.turnOnInterval;
|
||||||
g.setFont("6x8", font6x8FirstTextSize);
|
}
|
||||||
else
|
if (this.turnOffServiceTimeout){
|
||||||
g.setFont("6x8", font6x8DefaultTextSize);
|
clearTimeout(this.turnOffServiceTimeout)
|
||||||
|
}
|
||||||
var yPos = Bangle.appRect.y +
|
|
||||||
paddingY * (pos - 1) +
|
|
||||||
font6x8At4Size * Math.min(1, pos-1) +
|
|
||||||
font6x8At2Size * Math.max(0, pos-2);
|
|
||||||
g.drawString(line, 5, yPos, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawTime(now, pos){
|
|
||||||
var h = now.getHours();
|
|
||||||
var m = now.getMinutes();
|
|
||||||
var time = ">" + (""+h).substr(-2) + ":" + ("0"+m).substr(-2);
|
|
||||||
drawLine(time, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawDate(now, pos){
|
|
||||||
var dow = locale.dow(now, 1);
|
|
||||||
var date = locale.date(now, 1).substr(0,6) + locale.date(now, 1).substr(-2);
|
|
||||||
var locale_date = ">" + dow + " " + date;
|
|
||||||
drawLine(locale_date, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawInput(pos){
|
|
||||||
drawLine(">", pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawStepCount(pos){
|
|
||||||
var health = Bangle.getHealthStatus("day");
|
|
||||||
var steps_formated = ">Steps: " + health.steps;
|
|
||||||
drawLine(steps_formated, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawHRM(pos){
|
|
||||||
if(heartRate != 0)
|
|
||||||
drawLine(">HR: " + parseInt(heartRate), pos);
|
|
||||||
else
|
|
||||||
drawLine(">HR: unknown", pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawAltitude(pos){
|
|
||||||
if(altitude > 0)
|
|
||||||
drawLine(">Alt: " + altitude.toFixed(1) + "m", pos);
|
|
||||||
else
|
|
||||||
drawLine(">Alt: unknown", pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawMotion(pos){
|
|
||||||
var health = Bangle.getHealthStatus('last');
|
|
||||||
var steps_formated = ">Motion: " + parseInt(health.movement);
|
|
||||||
drawLine(steps_formated, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -----------------------------------------------
|
|
||||||
Services functions (HRM, pressure, etc...)
|
|
||||||
-------------------------------------------------- */
|
|
||||||
|
|
||||||
function turnOnServices(){
|
|
||||||
if(clock.showHRM){
|
|
||||||
Bangle.setHRMPower(true, "terminalclock");
|
|
||||||
}
|
|
||||||
if(clock.showAltitude){
|
|
||||||
Bangle.setBarometerPower(true, "terminalclock");
|
|
||||||
}
|
|
||||||
if(clock.powerSave){
|
|
||||||
setTimeout(function () {
|
|
||||||
turnOffServices();
|
turnOffServices();
|
||||||
}, 45000);
|
if (this.onLock) Bangle.removeListener('lock', this.onLock);
|
||||||
}
|
if (this.onHRM) Bangle.removeListener('HRM', this.onHRM);
|
||||||
|
if (this.onPressure) Bangle.removeListener('onPressure', this.onPressure);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------
|
||||||
|
Draw related of specific lines
|
||||||
|
-------------------------------- */
|
||||||
|
|
||||||
|
let drawLine = function(line, pos){
|
||||||
|
if(pos == 1)
|
||||||
|
g.setFont("6x8", font6x8FirstTextSize);
|
||||||
|
else
|
||||||
|
g.setFont("6x8", font6x8DefaultTextSize);
|
||||||
|
|
||||||
|
let yPos = Bangle.appRect.y +
|
||||||
|
paddingY * (pos - 1) +
|
||||||
|
font6x8At4Size * Math.min(1, pos-1) +
|
||||||
|
font6x8At2Size * Math.max(0, pos-2);
|
||||||
|
g.drawString(line, 5, yPos, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
let drawTime = function(now, pos){
|
||||||
|
let h = now.getHours();
|
||||||
|
let m = now.getMinutes();
|
||||||
|
let time = ">" + (""+h).substr(-2) + ":" + ("0"+m).substr(-2);
|
||||||
|
drawLine(time, pos);
|
||||||
|
};
|
||||||
|
|
||||||
|
let drawDate = function(now, pos){
|
||||||
|
let dow = locale.dow(now, 1);
|
||||||
|
let date = locale.date(now, 1).substr(0,6) + locale.date(now, 1).substr(-2);
|
||||||
|
let locale_date = ">" + dow + " " + date;
|
||||||
|
drawLine(locale_date, pos);
|
||||||
|
};
|
||||||
|
|
||||||
|
let drawInput = function(pos){
|
||||||
|
drawLine(">", pos);
|
||||||
|
};
|
||||||
|
|
||||||
|
let drawStepCount = function(pos){
|
||||||
|
let health = Bangle.getHealthStatus("day");
|
||||||
|
let steps_formated = ">Steps: " + health.steps;
|
||||||
|
drawLine(steps_formated, pos);
|
||||||
|
};
|
||||||
|
|
||||||
|
let drawHRM = function(pos){
|
||||||
|
if(heartRate != 0)
|
||||||
|
drawLine(">HR: " + parseInt(heartRate), pos);
|
||||||
|
else
|
||||||
|
drawLine(
|
||||||
|
">HR: " + parseInt(Math.round(Bangle.getHealthStatus().bpm||Bangle.getHealthStatus("last").bpm)),
|
||||||
|
pos);
|
||||||
|
};
|
||||||
|
|
||||||
|
let drawAltitude = function(pos){
|
||||||
|
if(altitude > 0)
|
||||||
|
drawLine(">Alt: " + altitude.toFixed(1) + "m", pos);
|
||||||
|
else
|
||||||
|
drawLine(">Alt: unknown", pos);
|
||||||
|
};
|
||||||
|
|
||||||
|
let drawMotion = function(pos){
|
||||||
|
let health = Bangle.getHealthStatus('last');
|
||||||
|
let steps_formated = ">Motion: " + parseInt(health.movement);
|
||||||
|
drawLine(steps_formated, pos);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
Services functions (HRM, pressure, etc...)
|
||||||
|
-------------------------------------------------- */
|
||||||
|
|
||||||
|
let turnOnServices = function(){
|
||||||
|
if(clock.showHRM){
|
||||||
|
Bangle.setHRMPower(true, "terminalclock");
|
||||||
|
}
|
||||||
|
if(clock.showAltitude){
|
||||||
|
Bangle.setBarometerPower(true, "terminalclock");
|
||||||
|
}
|
||||||
|
if(clock.powerSave){
|
||||||
|
clock.turnOffServiceTimeout = setTimeout(function () {
|
||||||
|
turnOffServices();
|
||||||
|
}, 45000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let turnOffServices = function(){
|
||||||
|
if(clock.showHRM){
|
||||||
|
Bangle.setHRMPower(false, "terminalclock");
|
||||||
|
}
|
||||||
|
if(clock.showAltitude){
|
||||||
|
Bangle.setBarometerPower(false, "terminalclock");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// set the lock and unlock actions
|
||||||
|
clock.onLock = lock_event => {
|
||||||
|
if (lock_event) lock();
|
||||||
|
else unlock();
|
||||||
|
};
|
||||||
|
Bangle.on("lock", clock.onLock);
|
||||||
|
|
||||||
|
clock.onHRM = hrmInfo => {
|
||||||
|
if(hrmInfo.confidence >= clock.HRMinConfidence)
|
||||||
|
heartRate = hrmInfo.bpm;
|
||||||
|
};
|
||||||
|
Bangle.on('HRM', clock.onHRM);
|
||||||
|
|
||||||
|
const MEDIANLENGTH = 20; // technical
|
||||||
|
let avr = [], median; // technical
|
||||||
|
clock.onPressure = pressureInfo => {
|
||||||
|
while (avr.length>MEDIANLENGTH) avr.pop();
|
||||||
|
avr.unshift(pressureInfo.altitude);
|
||||||
|
median = avr.slice().sort();
|
||||||
|
if (median.length>10) {
|
||||||
|
let mid = median.length>>1;
|
||||||
|
altitude = E.sum(median.slice(mid-4,mid+5)) / 9;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
altitude = pressureInfo.altitude;
|
||||||
|
};
|
||||||
|
Bangle.on('pressure', clock.onPressure);
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------------------------------
|
||||||
|
Clock related functions but not in the ClockFace module
|
||||||
|
---------------------------------------------------- */
|
||||||
|
|
||||||
|
let unlock = function(){
|
||||||
|
if(clock.powerSave){
|
||||||
|
turnOnServices();
|
||||||
|
}
|
||||||
|
clock.precision = clock.unlock_precision;
|
||||||
|
clock.tick();
|
||||||
|
};
|
||||||
|
|
||||||
|
let lock = function(){
|
||||||
|
clock.precision = clock.lock_precision;
|
||||||
|
clock.tick();
|
||||||
|
};
|
||||||
|
|
||||||
|
// starting the clock
|
||||||
|
clock.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
function turnOffServices(){
|
|
||||||
if(clock.showHRM){
|
|
||||||
Bangle.setHRMPower(false, "terminalclock");
|
|
||||||
}
|
|
||||||
if(clock.showAltitude){
|
|
||||||
Bangle.setBarometerPower(false, "terminalclock");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bangle.on('HRM',function(hrmInfo) {
|
|
||||||
if(hrmInfo.confidence >= clock.HRMinConfidence)
|
|
||||||
heartRate = hrmInfo.bpm;
|
|
||||||
});
|
|
||||||
|
|
||||||
const MEDIANLENGTH = 20; // technical
|
|
||||||
var avr = [], median; // technical
|
|
||||||
Bangle.on('pressure', function(e) {
|
|
||||||
while (avr.length>MEDIANLENGTH) avr.pop();
|
|
||||||
avr.unshift(e.altitude);
|
|
||||||
median = avr.slice().sort();
|
|
||||||
if (median.length>10) {
|
|
||||||
var mid = median.length>>1;
|
|
||||||
altitude = E.sum(median.slice(mid-4,mid+5)) / 9;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -------------------------------------------------
|
|
||||||
Clock related functions but not in the ClockFace module
|
|
||||||
---------------------------------------------------- */
|
|
||||||
|
|
||||||
function unlock(){
|
|
||||||
if(clock.powerSave){
|
|
||||||
turnOnServices();
|
|
||||||
}
|
|
||||||
clock.precision = clock.unlock_precision;
|
|
||||||
clock.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
function lock(){
|
|
||||||
clock.precision = clock.lock_precision;
|
|
||||||
clock.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
// starting the clock
|
|
||||||
clock.start();
|
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
"name": "Terminal Clock",
|
"name": "Terminal Clock",
|
||||||
"shortName":"Terminal Clock",
|
"shortName":"Terminal Clock",
|
||||||
"description": "A terminal cli like clock displaying multiple sensor data",
|
"description": "A terminal cli like clock displaying multiple sensor data",
|
||||||
"version":"0.08",
|
"version":"0.09",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
"tags": "clock",
|
"tags": "clock",
|
||||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||||
"allow_emulator": true,
|
"allow_emulator": false,
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name": "terminalclock.app.js","url": "app.js"},
|
{"name": "terminalclock.app.js","url": "app.js"},
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"description": "Simple and slim battery widget with charge status and percentage",
|
"description": "Simple and slim battery widget with charge status and percentage",
|
||||||
"tags": "widget,battery",
|
"tags": "widget,battery",
|
||||||
|
"provides_widgets" : ["battery"],
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"wid_a_battery_widget.wid.js","url":"widget.js"}
|
{"name":"wid_a_battery_widget.wid.js","url":"widget.js"}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@
|
||||||
0.02: Change font to 5x9 7 segment-style
|
0.02: Change font to 5x9 7 segment-style
|
||||||
Add settings page
|
Add settings page
|
||||||
Add option to show seconds
|
Add option to show seconds
|
||||||
|
0.03: Fix Bell not appearing on alarms > 24h and redrawing interval
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "widalarmeta",
|
"id": "widalarmeta",
|
||||||
"name": "Alarm & Timer ETA",
|
"name": "Alarm & Timer ETA",
|
||||||
"shortName": "Alarm ETA",
|
"shortName": "Alarm ETA",
|
||||||
"version": "0.02",
|
"version": "0.03",
|
||||||
"description": "A widget that displays the time to the next Alarm or Timer in hours and minutes, maximum 24h (configurable).",
|
"description": "A widget that displays the time to the next Alarm or Timer in hours and minutes, maximum 24h (configurable).",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
&& require("sched").getTimeToAlarm(alarm)
|
&& require("sched").getTimeToAlarm(alarm)
|
||||||
})
|
})
|
||||||
.filter(a => a !== undefined);
|
.filter(a => a !== undefined);
|
||||||
const next = Math.min.apply(null, times);
|
const next = times.length > 0 ? Math.min.apply(null, times) : 0;
|
||||||
let calcWidth = 0;
|
let calcWidth = 0;
|
||||||
let drawSeconds = false;
|
let drawSeconds = false;
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
if (drawSeconds) {
|
if (drawSeconds) {
|
||||||
calcWidth += 3*5;
|
calcWidth += 3*5;
|
||||||
}
|
}
|
||||||
} else if (times.length > 0 && config.drawBell) {
|
} else if (config.drawBell && alarms.some(alarm=>alarm.on&&(alarm.hidden!==true))) {
|
||||||
// next alarm too far in future, draw only widalarm bell
|
// next alarm too far in future, draw only widalarm bell
|
||||||
g.reset().drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y);
|
g.reset().drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y);
|
||||||
calcWidth = 24;
|
calcWidth = 24;
|
||||||
|
|
@ -57,8 +57,13 @@
|
||||||
if (timeout === 0) {
|
if (timeout === 0) {
|
||||||
timeout += period;
|
timeout += period;
|
||||||
}
|
}
|
||||||
setTimeout(()=>{
|
|
||||||
WIDGETS["widalarmeta"].draw(WIDGETS["widalarmeta"]);
|
if (this.timeoutId !== undefined) {
|
||||||
|
clearTimeout(this.timeoutId);
|
||||||
|
}
|
||||||
|
this.timeoutId = setTimeout(()=>{
|
||||||
|
this.timeoutId = undefined;
|
||||||
|
this.draw();
|
||||||
}, timeout);
|
}, timeout);
|
||||||
} /* draw */
|
} /* draw */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,5 @@
|
||||||
0.14: Fix drawing the bar when charging
|
0.14: Fix drawing the bar when charging
|
||||||
0.15: Added option to always display the icon when charging (useful if 'hide if charge greater than' is enabled)
|
0.15: Added option to always display the icon when charging (useful if 'hide if charge greater than' is enabled)
|
||||||
0.16: Increase screen update rate when charging
|
0.16: Increase screen update rate when charging
|
||||||
|
0.17: Add option 'Remove Jitter'='Drop only' to prevent percentage from getting up again when not charging
|
||||||
|
Add option to disable vibration when charger connects
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "widbatpc",
|
"id": "widbatpc",
|
||||||
"name": "Battery Level Widget (with percentage)",
|
"name": "Battery Level Widget (with percentage)",
|
||||||
"shortName": "Battery Widget",
|
"shortName": "Battery Widget",
|
||||||
"version": "0.16",
|
"version": "0.17",
|
||||||
"description": "Show the current battery level and charging status in the top right of the clock, with charge percentage",
|
"description": "Show the current battery level and charging status in the top right of the clock, with charge percentage",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
(function(back) {
|
(function(back) {
|
||||||
const SETTINGS_FILE = 'widbatpc.json'
|
const SETTINGS_FILE = 'widbatpc.json'
|
||||||
const COLORS = ['By Level', 'Green', 'Monochrome']
|
const COLORS = ['By Level', 'Green', 'Monochrome']
|
||||||
|
const RM_JITTER_OPTIONS = [/*LANG*/'Off', /*LANG*/'Drop only'];
|
||||||
|
|
||||||
// initialize with default settings...
|
// initialize with default settings...
|
||||||
let s = {
|
let s = {
|
||||||
|
|
@ -14,6 +15,8 @@
|
||||||
'charger': true,
|
'charger': true,
|
||||||
'hideifmorethan': 100,
|
'hideifmorethan': 100,
|
||||||
'alwaysoncharge': false,
|
'alwaysoncharge': false,
|
||||||
|
'removejitter': 0,
|
||||||
|
'buzzoncharge': true,
|
||||||
}
|
}
|
||||||
// ...and overwrite them with any saved values
|
// ...and overwrite them with any saved values
|
||||||
// This way saved values are preserved if a new version adds more settings
|
// This way saved values are preserved if a new version adds more settings
|
||||||
|
|
@ -28,7 +31,9 @@
|
||||||
return function (value) {
|
return function (value) {
|
||||||
s[key] = value;
|
s[key] = value;
|
||||||
storage.write(SETTINGS_FILE, s);
|
storage.write(SETTINGS_FILE, s);
|
||||||
WIDGETS["batpc"].reload();
|
if ("WIDGETS" in global && WIDGETS["batpc"] !== undefined) {
|
||||||
|
WIDGETS["batpc"].reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,17 +41,17 @@
|
||||||
const menu = {
|
const menu = {
|
||||||
'': { 'title': 'Battery Widget' },
|
'': { 'title': 'Battery Widget' },
|
||||||
'< Back': back,
|
'< Back': back,
|
||||||
'Percentage': {
|
/*LANG*/'Percentage': {
|
||||||
value: s.percentage,
|
value: s.percentage,
|
||||||
format: onOffFormat,
|
format: onOffFormat,
|
||||||
onchange: save('percentage'),
|
onchange: save('percentage'),
|
||||||
},
|
},
|
||||||
'Charging Icon': {
|
/*LANG*/'Charging Icon': {
|
||||||
value: s.charger,
|
value: s.charger,
|
||||||
format: onOffFormat,
|
format: onOffFormat,
|
||||||
onchange: save('charger'),
|
onchange: save('charger'),
|
||||||
},
|
},
|
||||||
'Color': {
|
/*LANG*/'Color': {
|
||||||
format: () => s.color,
|
format: () => s.color,
|
||||||
onchange: function () {
|
onchange: function () {
|
||||||
// cycles through options
|
// cycles through options
|
||||||
|
|
@ -56,12 +61,12 @@
|
||||||
save('color')(s.color)
|
save('color')(s.color)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'Fill Bar': {
|
/*LANG*/'Fill Bar': {
|
||||||
value: s.fillbar,
|
value: s.fillbar,
|
||||||
format: onOffFormat,
|
format: onOffFormat,
|
||||||
onchange: save('fillbar'),
|
onchange: save('fillbar'),
|
||||||
},
|
},
|
||||||
'Hide if >': {
|
/*LANG*/'Hide if >': {
|
||||||
value: s.hideifmorethan||100,
|
value: s.hideifmorethan||100,
|
||||||
min: 10,
|
min: 10,
|
||||||
max : 100,
|
max : 100,
|
||||||
|
|
@ -69,11 +74,22 @@
|
||||||
format: x => x+"%",
|
format: x => x+"%",
|
||||||
onchange: save('hideifmorethan'),
|
onchange: save('hideifmorethan'),
|
||||||
},
|
},
|
||||||
'Show on charge': { // Not sure if this is readable enough in the 'big' menu
|
/*LANG*/'Show on charge': { // Not sure if this is readable enough in the 'big' menu
|
||||||
value: s.alwaysoncharge,
|
value: s.alwaysoncharge,
|
||||||
format: onOffFormat,
|
format: onOffFormat,
|
||||||
onchange: save('alwaysoncharge'),
|
onchange: save('alwaysoncharge'),
|
||||||
},
|
},
|
||||||
|
/*LANG*/'Buzz on charge': {
|
||||||
|
value: s.buzzoncharge,
|
||||||
|
format: onOffFormat,
|
||||||
|
onchange: save('buzzoncharge'),
|
||||||
|
},
|
||||||
|
/*LANG*/'Remove Jitter': {
|
||||||
|
value: s.removejitter,
|
||||||
|
min: 0, max: 1,
|
||||||
|
format: v => RM_JITTER_OPTIONS[v],
|
||||||
|
onchange: save('removejitter'),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
E.showMenu(menu)
|
E.showMenu(menu)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
const intervalLow = 60000; // update time when not charging
|
const intervalLow = 60000; // update time when not charging
|
||||||
const intervalHigh = 2000; // update time when charging
|
const intervalHigh = 2000; // update time when charging
|
||||||
|
|
||||||
|
let prevMin = 100;
|
||||||
|
|
||||||
let COLORS = {};
|
let COLORS = {};
|
||||||
|
|
||||||
if (process.env.HWVERSION == 1) {
|
if (process.env.HWVERSION == 1) {
|
||||||
|
|
@ -33,6 +35,8 @@
|
||||||
'charger': true,
|
'charger': true,
|
||||||
'hideifmorethan': 100,
|
'hideifmorethan': 100,
|
||||||
'alwaysoncharge': false,
|
'alwaysoncharge': false,
|
||||||
|
'removejitter': 0, // 0 == off, 1 == downwards only
|
||||||
|
'buzzoncharge': true,
|
||||||
};
|
};
|
||||||
Object.keys(DEFAULTS).forEach(k=>{
|
Object.keys(DEFAULTS).forEach(k=>{
|
||||||
if (settings[k]===undefined) settings[k]=DEFAULTS[k];
|
if (settings[k]===undefined) settings[k]=DEFAULTS[k];
|
||||||
|
|
@ -88,8 +92,18 @@
|
||||||
// else...
|
// else...
|
||||||
var s = 39;
|
var s = 39;
|
||||||
var x = this.x, y = this.y;
|
var x = this.x, y = this.y;
|
||||||
const l = E.getBattery(),
|
let l = E.getBattery();
|
||||||
c = levelColor(l);
|
if (setting('removejitter') === 1) {
|
||||||
|
// if we have seen a battery percentage that was lower than current, use lower
|
||||||
|
if (Bangle.isCharging()) {
|
||||||
|
prevMin = l; // charging is the only way to increase percentage
|
||||||
|
} else if (prevMin >= l) {
|
||||||
|
prevMin = l;
|
||||||
|
} else {
|
||||||
|
l = prevMin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const c = levelColor(l);
|
||||||
|
|
||||||
if (Bangle.isCharging() && setting('charger')) {
|
if (Bangle.isCharging() && setting('charger')) {
|
||||||
g.setColor(chargerColor()).drawImage(atob(
|
g.setColor(chargerColor()).drawImage(atob(
|
||||||
|
|
@ -148,7 +162,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
Bangle.on('charging',function(charging) {
|
Bangle.on('charging',function(charging) {
|
||||||
if(charging) Bangle.buzz();
|
if (setting('buzzoncharge')) {
|
||||||
|
if(charging) Bangle.buzz();
|
||||||
|
}
|
||||||
update();
|
update();
|
||||||
g.flip();
|
g.flip();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue