forked from FOSS/BangleApps
Merge branch 'master' into mystic-dock
commit
ae6201f743
18
apps.json
18
apps.json
|
@ -3135,7 +3135,7 @@
|
|||
{ "id": "kitchen",
|
||||
"name": "Kitchen Combo",
|
||||
"icon": "kitchen.png",
|
||||
"version":"0.10",
|
||||
"version":"0.11",
|
||||
"description": "Combination of the Stepo, Walkersclock, Arrow and Waypointer apps into a multiclock format. 'Everything but the kitchen sink'. Requires firmware v2.08.167 or later",
|
||||
"tags": "tool,outdoors,gps",
|
||||
"type":"clock",
|
||||
|
@ -3146,7 +3146,6 @@
|
|||
{"name":"stepo.kit.js","url":"stepo.kit.js"},
|
||||
{"name":"gps.kit.js","url":"gps.kit.js"},
|
||||
{"name":"digi.kit.js","url":"digi.kit.js"},
|
||||
{"name":"heart.kit.js","url":"heart.kit.js"},
|
||||
{"name":"swatch.kit.js","url":"swatch.kit.js"},
|
||||
{"name":"compass.kit.js","url":"compass.kit.js"},
|
||||
{"name":"kitchen.img","url":"kitchen.icon.js","evaluate":true}
|
||||
|
@ -3273,5 +3272,20 @@
|
|||
{"name":"mysticdock.settings.js","url":"mystic-dock-settings.js"},
|
||||
{"name":"mysticdock.img","url":"mystic-dock-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "mysticclock",
|
||||
"name": "Mystic Clock",
|
||||
"icon": "mystic-clock.png",
|
||||
"version":"1.00",
|
||||
"description": "A retro-inspired watchface featuring time, date, and an interactive data display line.",
|
||||
"tags": "clock",
|
||||
"type":"clock",
|
||||
"readme": "README.md",
|
||||
"allow_emulator":true,
|
||||
"storage": [
|
||||
{"name":"mysticclock.app.js","url":"mystic-clock-app.js"},
|
||||
{"name":"mysticclock.settings.js","url":"mystic-clock-settings.js"},
|
||||
{"name":"mysticclock.img","url":"mystic-clock-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -36,6 +36,10 @@ charge.
|
|||
*BTN3* - invokes calibration ( can be cancelled if pressed accidentally)
|
||||
|
||||
|
||||
## Issues
|
||||
* detect when calibration data is missing
|
||||
|
||||
## Acknowledgement
|
||||
|
||||
This app is based in the work done by [jeffmer](https://github.com/jeffmer/JeffsBangleAppsDev)
|
||||
|
||||
|
|
|
@ -8,3 +8,4 @@
|
|||
0.08: Improved error handling for missing firmware features, added template app.kit.js
|
||||
0.09: Added heart rate monitor app
|
||||
0.10: Converted Stepo to use direct screen writes, added a Trip Counter feature to stepo
|
||||
0.11: Detect when waypoints.json is not present, error E-WPT
|
||||
|
|
|
@ -76,6 +76,9 @@ The following buttons depend on which face is currently in use
|
|||
## Heart
|
||||

|
||||
- A simple heart rate monitor, at present the app is just showing the raw value from HRM.bpm
|
||||
- This is an experimental app and not installed by default. The
|
||||
heart.kit.js file can be uploaded via the Espruino IDE if you want
|
||||
to try it out. Then reload the App.
|
||||
- BTN1, long press, turn heart rate monitor on / off
|
||||
|
||||
## Waypointer
|
||||
|
@ -226,12 +229,12 @@ I have settled on directly writing to the screen using the Graphics
|
|||
object (g.) for the compass App. This creates a bit of flicker when
|
||||
the arrow moves but is more reliable than using the ArrayBuffer.
|
||||
|
||||
v0.09: Since adding the heart rate monitor I have noticed that I can
|
||||
sometimes can a memory error when switch through the Apps back to the
|
||||
Stepo App. I think this can be cured by statically allocating the
|
||||
ArrayBuffer for stepo rather than using new everytime you switch back
|
||||
into the stepo watch face. The problem is that the bangle memory
|
||||
management / defragmentation is quite slow to run.
|
||||
v0.09: Since adding the heart rate monitor I have sometimes observed
|
||||
a low memory error when switching through the Apps back to the Stepo
|
||||
App. I think this can be cured by statically allocating the
|
||||
ArrayBuffer for stepo rather than using 'new' everytime you switch
|
||||
back into the stepo watch face. The problem is that the bangle
|
||||
memory management / defragmentation is quite slow to run.
|
||||
|
||||
v0.10: Revisited having a display buffer for the stepo part of the App.
|
||||
Now use direct screen writing as it means less memory allocation and
|
||||
|
@ -241,9 +244,13 @@ reduces chance of getting a memory error on switching watch faces.
|
|||
|
||||
The following error codes will be displayed if one of the dependancies is not met.
|
||||
|
||||
* E-STEPS - no pedomintor widget has been installed, please install the widpedom or the activepedom widgets
|
||||
* E-CALIB - no compass calibration data was found, see 'Compass Calibration'
|
||||
* E-FW - require firmware 2v08.187 or later to detect gps and compass power status
|
||||
* E-STEPS - no pedomintor widget has been installed, please install
|
||||
the widpedom or the activepedom widgets
|
||||
* E-CALIB - no compass calibration data was found, see 'Compass
|
||||
Calibration'
|
||||
* E-FW - require firmware 2v08.187 or later to detect gps and compass
|
||||
power status
|
||||
* E-WPT - missing waypoints.json file
|
||||
|
||||
### Issues / Future enhancements
|
||||
|
||||
|
@ -254,3 +261,5 @@ The following error codes will be displayed if one of the dependancies is not me
|
|||
seconds after the LCD goes off. At present I just rely on using
|
||||
the GPSSetup app and set the GPS power mode that I want.
|
||||
* Add a small graph to the heart rate monitor app
|
||||
* Add a facility to call the Arrow calibration process
|
||||
* Maybe create waypoints.json file if missing
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// annexed code that might be worth keeping
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
Screen Buffer Object that can be shared between faces
|
||||
|
||||
Making into a Class like this means we allocate the memory once
|
||||
and avoid fragmenting the memory when we switch in and out of faces
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
function BUF() {
|
||||
this.pal4color = new Uint16Array([0x0000,0xFFFF,0x7BEF,0xAFE5],0,2); // b,w,grey,greenyellow
|
||||
this.pal4red = new Uint16Array([0x0000,0xFFFF,0xF800,0xAFE5],0,2); // b,w,red,greenyellow
|
||||
this.buf = Graphics.createArrayBuffer(120,120,2,{msb:true});
|
||||
}
|
||||
|
||||
BUF.prototype.flip = function(x,y) {
|
||||
g.drawImage({width:120,height:120,bpp:2, buffer:this.buf.buffer, palette:this.pal4color}, x, y);
|
||||
this.buf.clear();
|
||||
}
|
||||
|
||||
BUF.prototype.flip_red = function(x,y) {
|
||||
g.drawImage({width:120,height:120,bpp:2, buffer:this.buf.buffer, palette:this.pal4red}, x, y);
|
||||
this.buf.clear();
|
||||
}
|
||||
|
||||
let bufObj = new BUF();
|
||||
|
|
@ -17,13 +17,12 @@
|
|||
}
|
||||
|
||||
function init(gps,sw, hrm) {
|
||||
showMem("compass init() START");
|
||||
gpsObject = gps;
|
||||
intervalRefSec = undefined;
|
||||
bearing = 0; // always point north if GPS is off
|
||||
heading = 0;
|
||||
oldHeading = 0;
|
||||
previous = {hding:"-", bs:"-", dst:"-", wp_name:"-", course:999};
|
||||
resetPrevious();
|
||||
loc = require("locale");
|
||||
CALIBDATA = require("Storage").readJSON("magnav.json",1)||null;
|
||||
getWaypoint();
|
||||
|
@ -34,12 +33,9 @@
|
|||
*/
|
||||
if (!Bangle.isCompassOn()) Bangle.setCompassPower(1);
|
||||
gps.determineGPSState();
|
||||
|
||||
showMem("compass init() END");
|
||||
}
|
||||
|
||||
function freeResources() {
|
||||
showMem("compass freeResources() START");
|
||||
gpsObject = undefined;
|
||||
intervalRefSec = undefined;
|
||||
previous = undefined;
|
||||
|
@ -50,7 +46,6 @@
|
|||
CALIBDATA = undefined;
|
||||
wp = undefined;
|
||||
if (Bangle.isCompassOn !== undefined && Bangle.isCompassOn()) Bangle.setCompassPower(0);
|
||||
showMem("compass freeResources() END");
|
||||
}
|
||||
|
||||
function startTimer() {
|
||||
|
@ -67,12 +62,6 @@
|
|||
if (Bangle.isCompassOn !== undefined && Bangle.isCompassOn()) Bangle.setCompassPower(0);
|
||||
}
|
||||
|
||||
function showMem(msg) {
|
||||
var val = process.memory();
|
||||
var str = msg + " " + Math.round(val.usage*100/val.total) + "%";
|
||||
log_debug(str);
|
||||
}
|
||||
|
||||
function onButtonShort(btn) {
|
||||
log_debug("onButtonShort()");
|
||||
if (gpsObject.getState() !== gpsObject.GPS_RUNNING) return;
|
||||
|
@ -206,12 +195,12 @@
|
|||
drawCompass(dir, 0xFFC0); // yellow
|
||||
oldHeading = dir;
|
||||
}
|
||||
|
||||
|
||||
if (gpsObject.getState() === gpsObject.GPS_RUNNING) {
|
||||
drawGPSData();
|
||||
} else {
|
||||
drawCompassHeading();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only used when acting as compass with GPS off
|
||||
|
|
|
@ -33,10 +33,10 @@ function nextFace(){
|
|||
// when you feel the buzzer you know you have done a long press
|
||||
function longPressCheck() {
|
||||
Bangle.buzz();
|
||||
debug_log("long PressCheck() buzz");
|
||||
debug_log("BUZZ, long press");
|
||||
if (pressTimer) {
|
||||
clearInterval(pressTimer);
|
||||
debug_log("clear pressTimer 2");
|
||||
debug_log("CLEAR pressTimer 2");
|
||||
pressTimer = undefined;
|
||||
}
|
||||
}
|
||||
|
@ -48,10 +48,10 @@ function buttonPressed(btn) {
|
|||
} else {
|
||||
firstPress = getTime();
|
||||
if (pressTimer) {
|
||||
debug_log("clear pressTimer 1");
|
||||
debug_log("CLEAR pressTimer 1");
|
||||
clearInterval(pressTimer);
|
||||
}
|
||||
debug_log("set pressTimer 1");
|
||||
debug_log("SET pressTimer 1");
|
||||
pressTimer = setInterval(longPressCheck, 1500);
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ function buttonPressed(btn) {
|
|||
function buttonReleased(btn) {
|
||||
var dur = getTime() - firstPress;
|
||||
if (pressTimer) {
|
||||
debug_log("clear pressTimer 3");
|
||||
debug_log("CLEAR pressTimer 3");
|
||||
clearInterval(pressTimer);
|
||||
pressTimer = undefined;
|
||||
}
|
||||
|
@ -256,7 +256,7 @@ GPS.prototype.processFix = function(fix) {
|
|||
this.gpsState = this.GPS_RUNNING;
|
||||
if (!this.last_fix.fix && !(require("Storage").readJSON("setting.json", 1) || {}).quiet) {
|
||||
Bangle.buzz(); // buzz on first position
|
||||
debug_log("GPS fix buzz");
|
||||
debug_log("BUZZ - gps fix");
|
||||
}
|
||||
this.last_fix = fix;
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ GPS.prototype.getWPdistance = function() {
|
|||
//log_debug(this.last_fix);
|
||||
//log_debug(this.wp_current);
|
||||
|
||||
if (this.wp_current.name === "NONE" || this.wp_current.lat === undefined || this.wp_current.lat === 0)
|
||||
if (this.wp_current.name === "E-WPT" || this.wp_current.name === "NONE" || this.wp_current.lat === undefined || this.wp_current.lat === 0)
|
||||
return 0;
|
||||
else
|
||||
return this.calcDistance(this.last_fix, this.wp_current);
|
||||
|
@ -313,14 +313,14 @@ GPS.prototype.getWPbearing = function() {
|
|||
//log_debug(this.last_fix);
|
||||
//log_debug(this.wp_current);
|
||||
|
||||
if (this.wp_current.name === "NONE" || this.wp_current.lat === undefined || this.wp_current.lat === 0)
|
||||
if (this.wp_current.name === "E-WPT" || this.wp_current.name === "NONE" || this.wp_current.lat === undefined || this.wp_current.lat === 0)
|
||||
return 0;
|
||||
else
|
||||
return this.calcBearing(this.last_fix, this.wp_current);
|
||||
}
|
||||
|
||||
GPS.prototype.loadFirstWaypoint = function() {
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"NONE"}];
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"E-WPT"}];
|
||||
this.wp_index = 0;
|
||||
this.wp_current = waypoints[this.wp_index];
|
||||
log_debug(this.wp_current);
|
||||
|
@ -332,7 +332,7 @@ GPS.prototype.getCurrentWaypoint = function() {
|
|||
}
|
||||
|
||||
GPS.prototype.waypointHasLocation = function() {
|
||||
if (this.wp_current.name === "NONE" || this.wp_current.lat === undefined || this.wp_current.lat === 0)
|
||||
if (this.wp_current.name === "E-WPT" || this.wp_current.name === "NONE" || this.wp_current.lat === undefined || this.wp_current.lat === 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
|
@ -340,12 +340,12 @@ GPS.prototype.waypointHasLocation = function() {
|
|||
|
||||
GPS.prototype.markWaypoint = function() {
|
||||
|
||||
if(this.wp_current.name === "NONE")
|
||||
if(this.wp_current.name === "E-WPT" || this.wp_current.name === "NONE")
|
||||
return;
|
||||
|
||||
log_debug("GPS::markWaypoint()");
|
||||
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"NONE"}];
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"E-WPT"}];
|
||||
this.wp_current = waypoints[this.wp_index];
|
||||
|
||||
if (this.waypointHasLocation()) {
|
||||
|
@ -360,7 +360,7 @@ GPS.prototype.markWaypoint = function() {
|
|||
}
|
||||
|
||||
GPS.prototype.nextWaypoint = function(inc) {
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"NONE"}];
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"E-WPT"}];
|
||||
this.wp_index+=inc;
|
||||
if (this.wp_index>=waypoints.length) this.wp_index=0;
|
||||
if (this.wp_index<0) this.wp_index = waypoints.length-1;
|
||||
|
@ -731,14 +731,14 @@ function TRIP() {
|
|||
|
||||
TRIP.prototype.resetTrip = function(steps) {
|
||||
this.tripStart = (0 + steps);
|
||||
console.log("resetTrip starting=" + this.tripStart);
|
||||
log_debug("resetTrip starting=" + this.tripStart);
|
||||
}
|
||||
|
||||
TRIP.prototype.getTrip = function(steps) {
|
||||
let tripSteps = (0 + steps) - this.tripStart;
|
||||
console.log("getTrip steps=" + steps);
|
||||
console.log("getTrip tripStart=" + this.tripStart);
|
||||
console.log("getTrip=" + tripSteps);
|
||||
log_debug("getTrip steps=" + steps);
|
||||
log_debug("getTrip tripStart=" + this.tripStart);
|
||||
log_debug("getTrip=" + tripSteps);
|
||||
return tripSteps;
|
||||
}
|
||||
|
||||
|
@ -758,7 +758,6 @@ Debug Object
|
|||
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
function DEBUG() {
|
||||
this.logfile = require("Storage").open("debug.log","a");
|
||||
}
|
||||
|
@ -770,7 +769,6 @@ DEBUG.prototype.log = function(msg) {
|
|||
}
|
||||
|
||||
debugObj = new DEBUG();
|
||||
*/
|
||||
|
||||
function debug_log(m) {
|
||||
//debugObj.log(m);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1.00: First published version.
|
|
@ -0,0 +1,40 @@
|
|||
# Mystic Clock for Bangle.js
|
||||
|
||||
A retro-inspired watchface featuring time, date, and an interactive data display line.
|
||||
|
||||
## Features
|
||||
|
||||
- 24 or 12-hour time (adjustable via the Settings menu)
|
||||
- Variable colors (also in the Settings)
|
||||
- Interactive data display line (use upper and lower watch-buttons to rotate between values)
|
||||
- Cover watch screen with your hand to put it to sleep (the watch, not your hand)
|
||||
- International localization of date (which can be disabled via the Settings if memory becomes an issue)
|
||||
|
||||
The interactive line rotates between the following items:
|
||||
|
||||
- Current time zone
|
||||
- Battery charge level
|
||||
- Device ID (derived from the last 4 of the MAC)
|
||||
- Memory usage
|
||||
- Firmware version
|
||||
|
||||
|
||||
## Inspirations
|
||||
|
||||
- [CLI Clock](https://github.com/espruino/BangleApps/tree/master/apps/cliock)
|
||||
- [Dev Clock](https://github.com/espruino/BangleApps/tree/master/apps/dclock)
|
||||
- [Digital Clock](https://github.com/espruino/BangleApps/tree/master/apps/digiclock)
|
||||
- [Simple Clock](https://github.com/espruino/BangleApps/tree/master/apps/sclock)
|
||||
- [Simplest Clock](https://github.com/espruino/BangleApps/tree/master/apps/simplest)
|
||||
|
||||
Icon adapted from [Public Domain Vectors](https://publicdomainvectors.org/en/free-clipart/Digital-clock-display-vector-image/10845.html).
|
||||
|
||||
|
||||
## Changelog
|
||||
|
||||
- 1.00: First published version. (June 2021)
|
||||
|
||||
|
||||
## Author
|
||||
|
||||
Eric Wooodward https://itsericwoodward.com/
|
|
@ -0,0 +1,215 @@
|
|||
/**
|
||||
* Mystic Clock for Bangle.js
|
||||
*
|
||||
* + Original Author: Eric Wooodward https://itsericwoodward.com/
|
||||
* + see README.md for details
|
||||
*/
|
||||
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
const timeFontSize = 6;
|
||||
const dataFontSize = 2;
|
||||
const font = "6x8";
|
||||
|
||||
const xyCenter = g.getWidth() / 2;
|
||||
|
||||
const yposTime = 75;
|
||||
const yposDate = 125;
|
||||
const yposSymbol = 160;
|
||||
const yposInfo = 220;
|
||||
|
||||
const settings = require('Storage').readJSON('mysticclock.json', 1) || {};
|
||||
const colors = ['white', 'blue', 'green', 'purple', 'red', 'teal', 'other'];
|
||||
const color = settings.color ? colors[settings.color] : 0;
|
||||
|
||||
const infoData = {
|
||||
'*GMT_MODE': {
|
||||
calc: () => (new Date()).toString().split(" ")[5],
|
||||
},
|
||||
BATT_MODE: {
|
||||
calc: () => `BATT: ${E.getBattery()}%`,
|
||||
},
|
||||
ID_MODE: {
|
||||
calc: () => {
|
||||
const val = NRF.getAddress().split(":");
|
||||
return `ID: ${val[4]}${val[5]}`;
|
||||
},
|
||||
},
|
||||
MEM_MODE: {
|
||||
calc: () => {
|
||||
const val = process.memory();
|
||||
return `MEM: ${Math.round(val.usage * 100 / val.total)}%`;
|
||||
},
|
||||
},
|
||||
VER_MODE: {
|
||||
calc: () => `FW: ${process.env.VERSION}`,
|
||||
},
|
||||
};
|
||||
const infoList = Object.keys(infoData).sort();
|
||||
let infoMode = infoList[0];
|
||||
|
||||
function setColor() {
|
||||
const colorCommands = {
|
||||
white: () => g.setColor(1, 1, 1),
|
||||
blue: () => g.setColor(0, 0, 1),
|
||||
green: () => g.setColor(0, 1, 0),
|
||||
purple: () => g.setColor(1, 0, 1),
|
||||
red: () => g.setColor(1, 0, 0),
|
||||
teal: () => g.setColor(0, 1, 1),
|
||||
other: () => g.setColor(1, 1, 0)
|
||||
};
|
||||
|
||||
// default if value unknown
|
||||
if (!color || !colorCommands[color]) return colorCommands.white();
|
||||
return colorCommands[color]();
|
||||
}
|
||||
|
||||
function getLocale() {
|
||||
return require('locale');
|
||||
}
|
||||
|
||||
function drawClock() {
|
||||
|
||||
// default draw styles
|
||||
g.reset();
|
||||
|
||||
// drawSting centered
|
||||
g.setFontAlign(0, 0);
|
||||
|
||||
// setup color
|
||||
setColor();
|
||||
|
||||
// get date
|
||||
const d = new Date();
|
||||
const dLocal = d.toString().split(" ");
|
||||
|
||||
const useLocale = !settings.useLocale;
|
||||
|
||||
const minutes = (`0${d.getMinutes()}`).substr(-2);
|
||||
const seconds = (`0${d.getSeconds()}`).substr(-2);
|
||||
|
||||
let hours = (`0${d.getHours()}`).substr(-2);
|
||||
let meridian = "";
|
||||
|
||||
if (settings.use12Hour) {
|
||||
hours = parseInt(hours, 10);
|
||||
meridian = 'AM';
|
||||
if (hours === 0) {
|
||||
hours = 12;
|
||||
}
|
||||
else if (hours >= 12) {
|
||||
meridian = 'PM';
|
||||
if (hours > 12) hours -= 12;
|
||||
}
|
||||
hours = (' ' + hours).substr(-2);
|
||||
}
|
||||
|
||||
g.setFont(font, timeFontSize);
|
||||
g.drawString(`${hours}${(d.getSeconds() % 2) ? ' ' : ':'}${minutes}`, xyCenter - 15, yposTime, true);
|
||||
g.setFont(font, dataFontSize);
|
||||
|
||||
if (settings.use12Hour) {
|
||||
g.drawString(seconds, xyCenter + 97, yposTime - 10, true);
|
||||
g.drawString(meridian, xyCenter + 97, yposTime + 10, true);
|
||||
}
|
||||
else {
|
||||
g.drawString(seconds, xyCenter + 97, yposTime + 10, true);
|
||||
}
|
||||
|
||||
// draw DoW, name of month, date, year
|
||||
g.setFont(font, dataFontSize);
|
||||
g.drawString([
|
||||
useLocale ? getLocale().dow(d, 1) : dLocal[0],
|
||||
useLocale ? getLocale().month(d, 1) : dLocal[1],
|
||||
d.getDate(),
|
||||
d.getFullYear()
|
||||
].join(" "), xyCenter, yposDate, true);
|
||||
|
||||
}
|
||||
|
||||
function drawInfo() {
|
||||
if (infoData[infoMode] && infoData[infoMode].calc) {
|
||||
// clear info
|
||||
g.setColor(0, 0, 0);
|
||||
g.fillRect(0, yposInfo - 8, 239, yposInfo + 25);
|
||||
|
||||
// draw info
|
||||
g.setFont(font, dataFontSize);
|
||||
setColor();
|
||||
g.drawString((infoData[infoMode].calc()), xyCenter, yposInfo, true);
|
||||
}
|
||||
}
|
||||
|
||||
function drawImage() {
|
||||
setColor();
|
||||
g.drawPoly([xyCenter - 100, yposSymbol, xyCenter + 100, yposSymbol, xyCenter, yposSymbol + 30], true);
|
||||
}
|
||||
|
||||
function drawAll() {
|
||||
drawClock();
|
||||
drawInfo();
|
||||
drawImage();
|
||||
}
|
||||
|
||||
function nextInfo() {
|
||||
let idx = infoList.indexOf(infoMode);
|
||||
if (idx > -1) {
|
||||
if (idx === infoList.length - 1) infoMode = infoList[0];
|
||||
else infoMode = infoList[idx + 1];
|
||||
}
|
||||
}
|
||||
|
||||
function prevInfo() {
|
||||
let idx = infoList.indexOf(infoMode);
|
||||
if (idx > -1) {
|
||||
if (idx === 0) infoMode = infoList[infoList.length - 1];
|
||||
else infoMode = infoList[idx - 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let secondInterval;
|
||||
|
||||
// handle LCD power state change
|
||||
Bangle.on('lcdPower', on => {
|
||||
|
||||
// stop running when screen turns off
|
||||
if (secondInterval) clearInterval(secondInterval);
|
||||
secondInterval = undefined;
|
||||
|
||||
// start running
|
||||
if (on) {
|
||||
secondInterval = setInterval(drawAll, 1000);
|
||||
drawAll(); // draw immediately
|
||||
}
|
||||
});
|
||||
|
||||
// cover screen to put it to sleep
|
||||
Bangle.on('touch', (button) => {
|
||||
if (button === 3 && Bangle.isLCDOn()) Bangle.setLCDPower(false);
|
||||
});
|
||||
|
||||
// clean app screen
|
||||
g.clear();
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
// if screen already active, draw now and start interval
|
||||
if (Bangle.isLCDOn()) {
|
||||
secondInterval = setInterval(drawAll, 1000);
|
||||
drawAll(); // draw immediately
|
||||
}
|
||||
|
||||
// show launcher when middle button pressed
|
||||
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
|
||||
|
||||
// rotate through info when the buttons are pressed
|
||||
setWatch(() => {
|
||||
nextInfo();
|
||||
drawAll();
|
||||
}, BTN3, { repeat: true });
|
||||
|
||||
setWatch(() => {
|
||||
prevInfo();
|
||||
drawAll();
|
||||
}, BTN1, { repeat: true });
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwkBIf4A/AH4A/AH4A/AH4ALs1msADCA4MGAgQDBBYIAGg93u92s4DBuEAAYN3swDCC5AhBuwMBg4XBuwEBs4dCC49nHgNwCQREBCYNnEYYXHHQQvBAAJZBAgRPEC5IOCu0GM4YLCuCGDAAREBHwtnJ41gDQIXEOAQvBDoZ7CuwjCWwimTJgLCFZojWEbwbWIAH4A/AH4A/AH4A/AH4AFA"))
|
|
@ -0,0 +1,41 @@
|
|||
// make sure to enclose the function in parentheses
|
||||
(function (back) {
|
||||
|
||||
const settings = require('Storage').readJSON('mysticclock.json',1)||{};
|
||||
const colors = ['White', 'Blue', 'Green', 'Purple', 'Red', 'Teal', 'Yellow'];
|
||||
const offon = ['Off','On'];
|
||||
const onoff = ['On','Off'];
|
||||
|
||||
function save(key, value) {
|
||||
settings[key] = value;
|
||||
require('Storage').writeJSON('mysticclock.json',settings);
|
||||
}
|
||||
|
||||
const appMenu = {
|
||||
'': {'title': 'Clock Settings'},
|
||||
'< Back': back,
|
||||
'Color': {
|
||||
value: 0|settings['color'],
|
||||
min:0,
|
||||
max:6,
|
||||
format: m => colors[m],
|
||||
onchange: m => {save('color', m)}
|
||||
},
|
||||
'12 Hour Clock': {
|
||||
value: 0|settings['use12Hour'],
|
||||
min:0,
|
||||
max:1,
|
||||
format: m => offon[m],
|
||||
onchange: m => {save('use12Hour', m)}
|
||||
},
|
||||
'Use Locale': {
|
||||
value: 0|settings['useLocale'],
|
||||
min:0,
|
||||
max:1,
|
||||
format: m => onoff[m],
|
||||
onchange: m => {save('useLocale', m)}
|
||||
}
|
||||
};
|
||||
E.showMenu(appMenu)
|
||||
|
||||
})
|
Binary file not shown.
After Width: | Height: | Size: 981 B |
Loading…
Reference in New Issue