mirror of https://github.com/espruino/BangleApps
Merge branch 'espruino:master' into master
commit
4fbca8aa0c
|
@ -1 +1,2 @@
|
|||
0.01: First version
|
||||
0.02: Support BangleJS2
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
(() => {
|
||||
const pin = process.env.HWVERSION === 2 ? D3 : D30;
|
||||
|
||||
var id;
|
||||
Bangle.on('charging', (charging) => {
|
||||
if (charging) {
|
||||
|
@ -6,9 +8,9 @@
|
|||
var max = 0;
|
||||
var count = 0;
|
||||
id = setInterval(() => {
|
||||
var d30 = analogRead(D30);
|
||||
if (max < d30) {
|
||||
max = d30;
|
||||
var battlvl = analogRead(pin);
|
||||
if (max < battlvl) {
|
||||
max = battlvl;
|
||||
count = 0;
|
||||
} else {
|
||||
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",
|
||||
"name": "Charge Gently",
|
||||
"version": "0.01",
|
||||
"version": "0.02",
|
||||
"description": "When charging, reminds you to disconnect the watch to prolong battery life.",
|
||||
"icon": "icon.png",
|
||||
"type": "bootloader",
|
||||
"tags": "battery",
|
||||
"supports": ["BANGLEJS"],
|
||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name": "chargent.boot.js", "url": "boot.min.js"}
|
||||
{"name": "chargent.boot.js", "url": "boot.js"}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
0.01: Moved from modules/clock_info.js
|
||||
0.02: Fix settings page
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ "id": "clock_info",
|
||||
"name": "Clock Info Module",
|
||||
"shortName": "Clock Info",
|
||||
"version":"0.01",
|
||||
"version":"0.02",
|
||||
"description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)",
|
||||
"icon": "app.png",
|
||||
"type": "module",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"readme": "README.md",
|
||||
"description": "Simple and slim battery widget with charge status and percentage",
|
||||
"tags": "widget,battery",
|
||||
"provides_widgets" : ["battery"],
|
||||
"storage": [
|
||||
{"name":"hwid_a_battery_widget.wid.js","url":"widget.js"}
|
||||
]
|
||||
|
|
|
@ -20,3 +20,4 @@
|
|||
still be loaded when they weren't supposed to.
|
||||
0.15: Ensure that we hide widgets if in fullscreen mode
|
||||
(So that widgets are still hidden if launcher is fast-loaded)
|
||||
0.16: Use firmware provided E.showScroller method
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
let scroll = 0;
|
||||
|
||||
let selectedItem = -1;
|
||||
const R = Bangle.appRect;
|
||||
const iconSize = 48;
|
||||
const appsN = Math.floor(R.w / iconSize);
|
||||
const whitespace = (R.w - appsN * iconSize) / (appsN + 1);
|
||||
const itemSize = iconSize + whitespace;
|
||||
|
||||
let drawItem = function(itemI, r) {
|
||||
g.clearRect(r.x, r.y, r.x + r.w - 1, r.y + r.h - 1);
|
||||
let x = 0;
|
||||
|
@ -61,36 +62,26 @@
|
|||
}
|
||||
x += iconSize;
|
||||
}
|
||||
drawText(itemI);
|
||||
drawText(itemI, r.y);
|
||||
};
|
||||
let drawItemAuto = function(i) {
|
||||
let y = idxToY(i);
|
||||
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) {
|
||||
|
||||
let drawText = function(i, appY) {
|
||||
const selectedApp = launchCache.apps[selectedItem];
|
||||
const idy = (selectedItem - (selectedItem % 3)) / 3;
|
||||
if (!selectedApp || i != idy) return;
|
||||
const appY = idxToY(idy) + iconSize / 2;
|
||||
appY = appY + itemSize/2;
|
||||
g.setFontAlign(0, 0, 0);
|
||||
g.setFont("12x20");
|
||||
const rect = g.stringMetrics(selectedApp.name);
|
||||
g.clearRect(
|
||||
R.w / 2 - rect.width / 2,
|
||||
appY - rect.height / 2,
|
||||
R.w / 2 + rect.width / 2,
|
||||
appY + rect.height / 2
|
||||
R.w / 2 - rect.width / 2 - 2,
|
||||
appY - rect.height / 2 - 2,
|
||||
R.w / 2 + rect.width / 2 + 1,
|
||||
appY + rect.height / 2 + 1
|
||||
);
|
||||
g.drawString(selectedApp.name, R.w / 2, appY);
|
||||
};
|
||||
|
||||
let selectItem = function(id, e) {
|
||||
const iconN = E.clip(Math.floor((e.x - R.x) / itemSize), 0, appsN - 1);
|
||||
const appId = id * appsN + iconN;
|
||||
|
@ -108,96 +99,32 @@
|
|||
}
|
||||
}
|
||||
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);
|
||||
let onDrag = function(e) {
|
||||
updateTimeout();
|
||||
g.setColor(g.theme.fg);
|
||||
g.setBgColor(g.theme.bg);
|
||||
let dy = e.dy;
|
||||
if (scroll + R.h - dy > itemsN * itemSize) {
|
||||
dy = scroll + R.h - itemsN * itemSize;
|
||||
}
|
||||
if (scroll - dy < 0) {
|
||||
dy = scroll;
|
||||
}
|
||||
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,
|
||||
|
||||
let back = ()=>{};
|
||||
if (settings.oneClickExit) back = Bangle.showClock;
|
||||
|
||||
let options = {
|
||||
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(); },
|
||||
c: itemsN,
|
||||
draw: drawItem,
|
||||
select: selectItem,
|
||||
back: back,
|
||||
remove: function() {
|
||||
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
|
||||
require("widget_utils").show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let scroller = E.showScroller(options);
|
||||
|
||||
let timeout;
|
||||
const updateTimeout = function(){
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "iconlaunch",
|
||||
"name": "Icon Launcher",
|
||||
"shortName" : "Icon launcher",
|
||||
"version": "0.15",
|
||||
"version": "0.16",
|
||||
"icon": "app.png",
|
||||
"description": "A launcher inspired by smartphones, with an icon-only scrollable menu.",
|
||||
"tags": "tool,system,launcher",
|
||||
|
|
|
@ -51,6 +51,8 @@ All touch and drag inputs related to this widget are cached/masked to prevent ac
|
|||
* __Min Value__
|
||||
_1%_ / _2%_ / _..._ / __10%__ / _..._ / _100%_
|
||||
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:
|
||||
* __TapSide__
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
oversize: 20,
|
||||
dragDelay: 500,
|
||||
minValue: 0.1,
|
||||
tapToLock: false,
|
||||
unlockSide: "",
|
||||
tapSide: "right",
|
||||
tapOn: "always",
|
||||
|
@ -119,6 +120,11 @@
|
|||
max: 100,
|
||||
step: 1
|
||||
},
|
||||
tapToLock: {
|
||||
title: ["on", "off"],
|
||||
value: [true, false],
|
||||
drawWidgets: false
|
||||
},
|
||||
unlockSide: {
|
||||
title: ["off", "left", "right", "top", "bottom", "front", "back"],
|
||||
value: ["", "left", "right", "top", "bottom", "front", "back"]
|
||||
|
@ -154,6 +160,7 @@
|
|||
"Oversize": getEntry("oversize"),
|
||||
"Drag Delay": getEntry("dragDelay"),
|
||||
"Min Value": getEntry("minValue"),
|
||||
"Tap to lock": getEntry("tapToLock"),
|
||||
"-- Unlock": 0,
|
||||
"TapSide": getEntry("unlockSide"),
|
||||
"-- Flash": 0,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
oversize: 20,
|
||||
dragDelay: 500,
|
||||
minValue: 0.1,
|
||||
tapToLock: false,
|
||||
unlockSide: "",
|
||||
tapSide: "right",
|
||||
tapOn: "always",
|
||||
|
@ -208,8 +209,12 @@
|
|||
w.dragStatus = "off";
|
||||
}, w.dragDelay, w);
|
||||
}
|
||||
if (w.tapToLock) {
|
||||
Bangle.setLocked(true);
|
||||
} else {
|
||||
// switch backlight
|
||||
w.changeValue();
|
||||
}
|
||||
// masks this touch event by messing up the event handler
|
||||
// see https://github.com/espruino/Espruino/issues/2151
|
||||
Bangle.removeListener("touch", w.touchListener);
|
||||
|
|
|
@ -13,3 +13,4 @@
|
|||
0.10: Fix: Do not wake when falling asleep
|
||||
0.11: Minor tweaks
|
||||
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,
|
||||
}
|
||||
}, 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();
|
||||
let buzzCount = schedSettings.buzzCount;
|
||||
let logs = [];
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "sleepphasealarm",
|
||||
"name": "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.",
|
||||
"icon": "app.png",
|
||||
"tags": "alarm",
|
||||
|
@ -14,6 +14,6 @@
|
|||
{"name":"sleepphasealarm.settings.js","url":"settings.js"},
|
||||
{"name":"sleepphasealarm.img","url":"app-icon.js","evaluate":true}
|
||||
],
|
||||
"data": [{"name":"sleepphasealarm.json","storageFile":true}],
|
||||
"data": [{"name":"sleepphasealarm.json"}],
|
||||
"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.08: Hide widgets instead of not loading them at all
|
||||
Use Clockface_menu for widgets and power saving settings
|
||||
0.09: Add default HRM value, default altitude value
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
const locale = require("locale");
|
||||
var heartRate = 0;
|
||||
var altitude = -9001;
|
||||
{
|
||||
const locale = require("locale");
|
||||
let heartRate = 0;
|
||||
let altitude = -9001;
|
||||
|
||||
const fontColor = g.theme.dark ? "#0f0" : "#000";
|
||||
// handling the differents versions of the Banglejs smartwatch screen sizes
|
||||
if (process.env.HWVERSION == 1){
|
||||
var paddingY = 3;
|
||||
var font6x8At4Size = 48;
|
||||
var font6x8At2Size = 27;
|
||||
var font6x8FirstTextSize = 6;
|
||||
var font6x8DefaultTextSize = 3;
|
||||
} else{
|
||||
var paddingY = 2;
|
||||
var font6x8At4Size = 32;
|
||||
var font6x8At2Size = 18;
|
||||
var font6x8FirstTextSize = 4;
|
||||
var font6x8DefaultTextSize = 2;
|
||||
}
|
||||
|
||||
// initialising the clockface
|
||||
const ClockFace = require("ClockFace");
|
||||
const clock = new ClockFace({
|
||||
const fontColor = g.theme.dark ? "#0f0" : "#000";
|
||||
// handling the differents versions of the Banglejs smartwatch screen sizes
|
||||
// default BJS2
|
||||
let paddingY = 2;
|
||||
let font6x8At4Size = 32;
|
||||
let font6x8At2Size = 18;
|
||||
let font6x8FirstTextSize = 4;
|
||||
let font6x8DefaultTextSize = 2;
|
||||
if (process.env.HWVERSION == 1){
|
||||
paddingY = 3;
|
||||
font6x8At4Size = 48;
|
||||
font6x8At2Size = 27;
|
||||
font6x8FirstTextSize = 6;
|
||||
font6x8DefaultTextSize = 3;
|
||||
}
|
||||
// initialising the clockface
|
||||
const ClockFace = require("ClockFace");
|
||||
const clock = new ClockFace({
|
||||
precision: 60,
|
||||
settingsFile: "terminalclock.json",
|
||||
|
||||
|
@ -34,6 +34,7 @@ const clock = new ClockFace({
|
|||
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;
|
||||
|
||||
["L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9"].forEach(k => {
|
||||
if (this[k]===undefined){
|
||||
if(k == "L2") this[k] = "Date";
|
||||
|
@ -49,24 +50,18 @@ const clock = new ClockFace({
|
|||
else if (this[k]==="Alt") this.showAltitude = true && process.env.HWVERSION == 2;
|
||||
});
|
||||
|
||||
// set the lock and unlock actions
|
||||
Bangle.on("lock", on => {
|
||||
if (on) lock();
|
||||
else unlock();
|
||||
});
|
||||
|
||||
// set the services (HRM, pressure sensor, etc....)
|
||||
if(!this.powerSave){
|
||||
turnOnServices();
|
||||
} else{
|
||||
setInterval(turnOnServices, this.PowerOnInterval*60000); // every PowerOnInterval min
|
||||
this.turnOnInterval = setInterval(turnOnServices, this.PowerOnInterval*60000); // every PowerOnInterval min
|
||||
}
|
||||
// start the clock unlocked
|
||||
unlock();
|
||||
},
|
||||
|
||||
draw: function (date) {
|
||||
var curPos = 1;
|
||||
let curPos = 1;
|
||||
g.setFontAlign(-1, -1);
|
||||
g.setColor(fontColor);
|
||||
drawTime(date, curPos);
|
||||
|
@ -82,75 +77,95 @@ const clock = new ClockFace({
|
|||
curPos++;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
/*
|
||||
// todo add fastloading when the memory leak is fixed
|
||||
remove: function() {
|
||||
if (this.turnOnInterval){
|
||||
clearInterval(this.turnOnInterval);
|
||||
delete this.turnOnInterval;
|
||||
}
|
||||
if (this.turnOffServiceTimeout){
|
||||
clearTimeout(this.turnOffServiceTimeout)
|
||||
}
|
||||
turnOffServices();
|
||||
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
|
||||
-------------------------------- */
|
||||
/* ----------------------------
|
||||
Draw related of specific lines
|
||||
-------------------------------- */
|
||||
|
||||
function drawLine(line, pos){
|
||||
let drawLine = function(line, pos){
|
||||
if(pos == 1)
|
||||
g.setFont("6x8", font6x8FirstTextSize);
|
||||
else
|
||||
g.setFont("6x8", font6x8DefaultTextSize);
|
||||
|
||||
var yPos = Bangle.appRect.y +
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
function drawTime(now, pos){
|
||||
var h = now.getHours();
|
||||
var m = now.getMinutes();
|
||||
var time = ">" + (""+h).substr(-2) + ":" + ("0"+m).substr(-2);
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
function drawInput(pos){
|
||||
let drawInput = function(pos){
|
||||
drawLine(">", pos);
|
||||
}
|
||||
};
|
||||
|
||||
function drawStepCount(pos){
|
||||
var health = Bangle.getHealthStatus("day");
|
||||
var steps_formated = ">Steps: " + health.steps;
|
||||
let drawStepCount = function(pos){
|
||||
let health = Bangle.getHealthStatus("day");
|
||||
let steps_formated = ">Steps: " + health.steps;
|
||||
drawLine(steps_formated, pos);
|
||||
}
|
||||
};
|
||||
|
||||
function drawHRM(pos){
|
||||
let drawHRM = function(pos){
|
||||
if(heartRate != 0)
|
||||
drawLine(">HR: " + parseInt(heartRate), pos);
|
||||
else
|
||||
drawLine(">HR: unknown", pos);
|
||||
}
|
||||
drawLine(
|
||||
">HR: " + parseInt(Math.round(Bangle.getHealthStatus().bpm||Bangle.getHealthStatus("last").bpm)),
|
||||
pos);
|
||||
};
|
||||
|
||||
function drawAltitude(pos){
|
||||
let drawAltitude = function(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);
|
||||
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...)
|
||||
-------------------------------------------------- */
|
||||
/* -----------------------------------------------
|
||||
Services functions (HRM, pressure, etc...)
|
||||
-------------------------------------------------- */
|
||||
|
||||
function turnOnServices(){
|
||||
let turnOnServices = function(){
|
||||
if(clock.showHRM){
|
||||
Bangle.setHRMPower(true, "terminalclock");
|
||||
}
|
||||
|
@ -158,54 +173,67 @@ function turnOnServices(){
|
|||
Bangle.setBarometerPower(true, "terminalclock");
|
||||
}
|
||||
if(clock.powerSave){
|
||||
setTimeout(function () {
|
||||
clock.turnOffServiceTimeout = setTimeout(function () {
|
||||
turnOffServices();
|
||||
}, 45000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function turnOffServices(){
|
||||
let turnOffServices = function(){
|
||||
if(clock.showHRM){
|
||||
Bangle.setHRMPower(false, "terminalclock");
|
||||
}
|
||||
if(clock.showAltitude){
|
||||
Bangle.setBarometerPower(false, "terminalclock");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Bangle.on('HRM',function(hrmInfo) {
|
||||
// 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
|
||||
var avr = [], median; // technical
|
||||
Bangle.on('pressure', function(e) {
|
||||
const MEDIANLENGTH = 20; // technical
|
||||
let avr = [], median; // technical
|
||||
clock.onPressure = pressureInfo => {
|
||||
while (avr.length>MEDIANLENGTH) avr.pop();
|
||||
avr.unshift(e.altitude);
|
||||
avr.unshift(pressureInfo.altitude);
|
||||
median = avr.slice().sort();
|
||||
if (median.length>10) {
|
||||
var mid = median.length>>1;
|
||||
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
|
||||
---------------------------------------------------- */
|
||||
|
||||
function unlock(){
|
||||
/* -------------------------------------------------
|
||||
Clock related functions but not in the ClockFace module
|
||||
---------------------------------------------------- */
|
||||
|
||||
let unlock = function(){
|
||||
if(clock.powerSave){
|
||||
turnOnServices();
|
||||
}
|
||||
clock.precision = clock.unlock_precision;
|
||||
clock.tick();
|
||||
}
|
||||
};
|
||||
|
||||
function lock(){
|
||||
let lock = function(){
|
||||
clock.precision = clock.lock_precision;
|
||||
clock.tick();
|
||||
}
|
||||
};
|
||||
|
||||
// starting the clock
|
||||
clock.start();
|
||||
// starting the clock
|
||||
clock.start();
|
||||
}
|
|
@ -3,12 +3,12 @@
|
|||
"name": "Terminal Clock",
|
||||
"shortName":"Terminal Clock",
|
||||
"description": "A terminal cli like clock displaying multiple sensor data",
|
||||
"version":"0.08",
|
||||
"version":"0.09",
|
||||
"icon": "app.png",
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"allow_emulator": false,
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name": "terminalclock.app.js","url": "app.js"},
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"readme": "README.md",
|
||||
"description": "Simple and slim battery widget with charge status and percentage",
|
||||
"tags": "widget,battery",
|
||||
"provides_widgets" : ["battery"],
|
||||
"storage": [
|
||||
{"name":"wid_a_battery_widget.wid.js","url":"widget.js"}
|
||||
]
|
||||
|
|
|
@ -2,3 +2,5 @@
|
|||
0.02: Change font to 5x9 7 segment-style
|
||||
Add settings page
|
||||
Add option to show seconds
|
||||
0.03: Fix Bell not appearing on alarms > 24h and redrawing interval
|
||||
Update to match the default alarm widget, and not show itself when an alarm is hidden.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "widalarmeta",
|
||||
"name": "Alarm & Timer 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).",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
|
|
|
@ -8,8 +8,13 @@
|
|||
}, require("Storage").readJSON("widalarmeta.json",1) || {});
|
||||
|
||||
function draw() {
|
||||
const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm)).filter(a => a !== undefined);
|
||||
const next = Math.min.apply(null, times);
|
||||
const times = alarms
|
||||
.map(alarm => {
|
||||
alarm.hidden !== true
|
||||
&& require("sched").getTimeToAlarm(alarm)
|
||||
})
|
||||
.filter(a => a !== undefined);
|
||||
const next = times.length > 0 ? Math.min.apply(null, times) : 0;
|
||||
let calcWidth = 0;
|
||||
let drawSeconds = false;
|
||||
|
||||
|
@ -34,7 +39,7 @@
|
|||
if (drawSeconds) {
|
||||
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
|
||||
g.reset().drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y);
|
||||
calcWidth = 24;
|
||||
|
@ -52,8 +57,13 @@
|
|||
if (timeout === 0) {
|
||||
timeout += period;
|
||||
}
|
||||
setTimeout(()=>{
|
||||
WIDGETS["widalarmeta"].draw(WIDGETS["widalarmeta"]);
|
||||
|
||||
if (this.timeoutId !== undefined) {
|
||||
clearTimeout(this.timeoutId);
|
||||
}
|
||||
this.timeoutId = setTimeout(()=>{
|
||||
this.timeoutId = undefined;
|
||||
this.draw();
|
||||
}, timeout);
|
||||
} /* draw */
|
||||
|
||||
|
|
|
@ -13,3 +13,5 @@
|
|||
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.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",
|
||||
"name": "Battery Level Widget (with percentage)",
|
||||
"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",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
(function(back) {
|
||||
const SETTINGS_FILE = 'widbatpc.json'
|
||||
const COLORS = ['By Level', 'Green', 'Monochrome']
|
||||
const RM_JITTER_OPTIONS = [/*LANG*/'Off', /*LANG*/'Drop only'];
|
||||
|
||||
// initialize with default settings...
|
||||
let s = {
|
||||
|
@ -14,6 +15,8 @@
|
|||
'charger': true,
|
||||
'hideifmorethan': 100,
|
||||
'alwaysoncharge': false,
|
||||
'removejitter': 0,
|
||||
'buzzoncharge': true,
|
||||
}
|
||||
// ...and overwrite them with any saved values
|
||||
// This way saved values are preserved if a new version adds more settings
|
||||
|
@ -28,25 +31,27 @@
|
|||
return function (value) {
|
||||
s[key] = value;
|
||||
storage.write(SETTINGS_FILE, s);
|
||||
if ("WIDGETS" in global && WIDGETS["batpc"] !== undefined) {
|
||||
WIDGETS["batpc"].reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onOffFormat = b => (b ? 'on' : 'off')
|
||||
const menu = {
|
||||
'': { 'title': 'Battery Widget' },
|
||||
'< Back': back,
|
||||
'Percentage': {
|
||||
/*LANG*/'Percentage': {
|
||||
value: s.percentage,
|
||||
format: onOffFormat,
|
||||
onchange: save('percentage'),
|
||||
},
|
||||
'Charging Icon': {
|
||||
/*LANG*/'Charging Icon': {
|
||||
value: s.charger,
|
||||
format: onOffFormat,
|
||||
onchange: save('charger'),
|
||||
},
|
||||
'Color': {
|
||||
/*LANG*/'Color': {
|
||||
format: () => s.color,
|
||||
onchange: function () {
|
||||
// cycles through options
|
||||
|
@ -56,12 +61,12 @@
|
|||
save('color')(s.color)
|
||||
}
|
||||
},
|
||||
'Fill Bar': {
|
||||
/*LANG*/'Fill Bar': {
|
||||
value: s.fillbar,
|
||||
format: onOffFormat,
|
||||
onchange: save('fillbar'),
|
||||
},
|
||||
'Hide if >': {
|
||||
/*LANG*/'Hide if >': {
|
||||
value: s.hideifmorethan||100,
|
||||
min: 10,
|
||||
max : 100,
|
||||
|
@ -69,11 +74,22 @@
|
|||
format: x => x+"%",
|
||||
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,
|
||||
format: onOffFormat,
|
||||
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)
|
||||
})
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
const intervalLow = 60000; // update time when not charging
|
||||
const intervalHigh = 2000; // update time when charging
|
||||
|
||||
let prevMin = 100;
|
||||
|
||||
let COLORS = {};
|
||||
|
||||
if (process.env.HWVERSION == 1) {
|
||||
|
@ -33,6 +35,8 @@
|
|||
'charger': true,
|
||||
'hideifmorethan': 100,
|
||||
'alwaysoncharge': false,
|
||||
'removejitter': 0, // 0 == off, 1 == downwards only
|
||||
'buzzoncharge': true,
|
||||
};
|
||||
Object.keys(DEFAULTS).forEach(k=>{
|
||||
if (settings[k]===undefined) settings[k]=DEFAULTS[k];
|
||||
|
@ -88,8 +92,18 @@
|
|||
// else...
|
||||
var s = 39;
|
||||
var x = this.x, y = this.y;
|
||||
const l = E.getBattery(),
|
||||
c = levelColor(l);
|
||||
let l = E.getBattery();
|
||||
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')) {
|
||||
g.setColor(chargerColor()).drawImage(atob(
|
||||
|
@ -148,7 +162,9 @@
|
|||
}
|
||||
|
||||
Bangle.on('charging',function(charging) {
|
||||
if (setting('buzzoncharge')) {
|
||||
if(charging) Bangle.buzz();
|
||||
}
|
||||
update();
|
||||
g.flip();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue