Refactoring + added timer which can easily be started / stopped.

pull/1333/head
David Peer 2022-01-22 08:43:44 +01:00
parent ea028454af
commit cc64bfdd6a
5 changed files with 211 additions and 65 deletions

View File

@ -6,17 +6,19 @@ It looks like an analog clock, but its not! It shows the time digital - check th
The red hand shows the number of steps (0 = 0°, 2.5k = 90°, 5k = 180°, ...) and the The red hand shows the number of steps (0 = 0°, 2.5k = 90°, 5k = 180°, ...) and the
black one the battery level (100% = 0°, 75% = 270°, 50% = 180°, ...). black one the battery level (100% = 0°, 75% = 270°, 50% = 180°, ...).
The selected theme is also respected. Note that this watch face is in fullscreen The selected theme is also respected. Note that this watch face is in fullscreen
mode - widgets are still loaded in background... mode, but widgets are still loaded in background.
## Other features ## Other features
- If you have done more than 10k steps, the red hand and icon will turn green. - Set a timer - simply touch top (+5min.) or bottom (-5 min.).
- If the weather is available through the weather app, the outside temp. will be shown.
- If the battery is charged, the icons will change. - If the battery is charged, the icons will change.
- Shows outside temperature if gadgetbridge is connected with weather. - If you have done more than 10k steps, the red hand and icon will turn green.
- Shows current lock status of your bangle. - Shows current lock status of your bangle va a colored dot in the middle.
## Screenshots ## Screenshots
![](screenshot_1.png) ![](screenshot_1.png)
![](screenshot_2.png) ![](screenshot_2.png)
![](screenshot_3.png)
# Thanks # Thanks

View File

@ -1,5 +1,17 @@
const locale = require('locale'); /**
* NOT ANALOG CLOCK
*/
const locale = require('locale');
const storage = require('Storage')
const SETTINGS_FILE = "notanalog.setting.json";
let settings = {
alarm: -1,
};
let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
for (const key in saved_settings) {
settings[key] = saved_settings[key]
}
/* /*
* Set some important constants such as width, height and center * Set some important constants such as width, height and center
@ -10,10 +22,31 @@ var cx = W/2;
var cy = H/2; var cy = H/2;
var drawTimeout; var drawTimeout;
var state = {
color: "#ff0000",
steps: 0,
maxSteps: 10000,
bat: 0,
has_weather: false,
temp: "-"
}
var chargeImg = { var chargeImg = {
width : 32, height : 32, bpp : 1, width : 32, height : 32, bpp : 1,
transparent : 0, transparent : 0,
buffer : require("heatshrink").decompress(atob("AAMMAYUeAYUzAYVjAYXGAQMPxwDBj8cAYM73ADBuPwEAPg8E+gHAuFzgOAnHjAYMd40BwOPxkBwfHjEBw1j2ADBsPgBYPAAYIYBsEDFoPgg+AgPAg/AgeAhgJBgEYuf+AYM//BhBnAYBh1wKQXAAYM5wADBBQQoBAYQOCgA=")) buffer : E.toArrayBuffer(atob("AAAMAAAAHgAAADMAAABjAAAAxgAAD44AAB8cAAA7uAAAcfAMAODgPgDAcHMBgDjjAYAdxgGBj4wBg8cYAYZjsAGGYeABg8DgAQGAYAMAAOAHgAHAB8ADgAzgBwAYc/4AGD/4AAw4AAAOcAAAH8AAADmAAABwAAAA4AAAAMAAAAA="))
};
var alarmImg = {
width : 32, height : 32, bpp : 1,
transparent : 0,
buffer : E.toArrayBuffer(atob("AA/wAAAP8AAAD/AAAAGAAAABgAAAA8AABh/4YAd//uAH+B/gA+AHwAOAAcAHAPDgDgD4cA4A/HAcAP44HAD+OBwA/zgYAP8YGAD/GBj//xgc//84HH/+OBx//jgOP/xwDh/4cAcP8OAHg8HgA8ADwAHwD4AA//8AAD/8AAAP8AA="))
};
var stepsImg = {
width : 32, height : 32, bpp : 1,
transparent : 0,
buffer : E.toArrayBuffer(atob("AcAAAAPwAAAH8AAAB/gAAAf4AAAH/AAAD/wAAAf8AAAH/AfAB/wP4Af8H+AH/B/gB/wf4AP8P+AD+D/gAfg/4AGAP+AAPD/gAPw/4AD+P+AAfj/AAH4/wAB+H8AAPAeAAAAwAAAAPgAAAH8AAAB/AAAAfgAAAH4AAAA8AAAAOAA="))
}; };
@ -83,6 +116,23 @@ function drawBackground() {
} }
function drawState(){
g.setColor(state.color);
g.setFontAlign(1,0,0);
// Draw alarm
var highPrioImg = isAlarmEnabled() ? alarmImg :
Bangle.isCharging() ? chargeImg : undefined;
// As default, we draw weather if available, otherwise the steps symbol is shown.
if(!highPrioImg && state.has_weather){
g.setColor(g.theme.fg);
g.drawString(state.temp, cx+cx/2+15, cy+cy/2+10);
} else {
var img = highPrioImg ? highPrioImg : stepsImg;
g.drawImage(img, cx+cx/2 - img.width/2, cy+cy/2 - img.height/2+5);
}
}
function drawData() { function drawData() {
g.setFontAlign(0,0,0); g.setFontAlign(0,0,0);
@ -90,41 +140,23 @@ function drawData() {
// Set hand functions // Set hand functions
var drawBatteryHand = g.drawRotRect.bind(g,6,12,R-38); var drawBatteryHand = g.drawRotRect.bind(g,6,12,R-38);
var drawStepsHand = g.drawRotRect.bind(g,5,12,R-24); var drawDataHand = g.drawRotRect.bind(g,5,12,R-24);
// Draw state
g.setColor(g.theme.fg);
if(Bangle.isCharging()){
g.drawImage(chargeImg, cx+cx/2 - chargeImg.width/2, cy+cy/2 - chargeImg.height/2+5);
} else {
dataStr = "B-JS";
try {
weather = require('weather').get();
if (weather === undefined){
dataStr = "-";
} else {
dataStr = locale.temp(Math.round(weather.temp-273.15));
}
} catch(ex) {
}
g.setFontAlign(1,0,0);
g.drawString(dataStr, cx+cx/2+15, cy+cy/2+10);
}
// Draw battery hand // Draw battery hand
g.setColor(g.theme.fg);
g.setFontAlign(0,0,0); g.setFontAlign(0,0,0);
var bat = E.getBattery(); drawBatteryHand(parseInt(state.bat*360/100));
var maxBat = 100;
drawBatteryHand(parseInt(bat*360/maxBat));
// Draw step hand and icon // Draw data hand - depending on state
var steps = getSteps(); g.setColor(state.color);
var maxSteps = 10000; if(isAlarmEnabled()){
var stepsColor = steps > 10000 ? "#00ff00" : "#ff0000"; var alrm = getAlarmMinutes();
g.setColor(stepsColor); drawDataHand(parseInt(alrm*360/60));
drawStepsHand(parseInt(steps*360/maxSteps)); return;
}
// Default are the steps
drawDataHand(parseInt(state.steps*360/state.maxSteps));
} }
@ -150,15 +182,6 @@ function drawTime(){
var m2 = m < 10 ? m : m - m1*10; var m2 = m < 10 ? m : m - m1*10;
g.drawString(m2, cx, H-posY); g.drawString(m2, cx, H-posY);
g.drawString(m1, posX-1, cy+5); g.drawString(m1, posX-1, cy+5);
// Connect
var rP = 24;
var w = 4;
g.setColor(1,0,0);
for(var dy=-w;dy <= w; dy += 1){
g.drawLine(cx+rP, posY+rP/2+dy+5, W-posX-rP, cy-rP);
g.drawLine(posX-2+rP, cy+rP/2+dy+5, cx-rP, H-posY+2-rP);
}
} }
@ -179,28 +202,62 @@ function drawLock(){
g.setColor(g.theme.fg); g.setColor(g.theme.fg);
g.fillCircle(cx, cy, 7); g.fillCircle(cx, cy, 7);
var c = Bangle.isLocked() ? "#ff0000" : g.theme.bg; var c = Bangle.isLocked() ? state.color : g.theme.bg;
g.setColor(c); g.setColor(c);
g.fillCircle(cx, cy, 4); g.fillCircle(cx, cy, 4);
} }
function handleState(){
// Set battery
state.bat = E.getBattery();
// Set steps
state.steps = getSteps();
state.maxSteps = 10000;
// Set theme color
state.color = isAlarmEnabled() ? "#FF6A00" :
state.steps > state.maxSteps ? "#00ff00" :
"#ff0000";
// Set weather
state.has_weather = true;
try {
weather = require('weather').get();
if (weather === undefined){
state.temp = "-";
} else {
state.temp = locale.temp(Math.round(weather.temp-273.15));
}
} catch(ex) {
state.has_weather = false;
}
}
function draw(){ function draw(){
// Clear watch face // Execute handlers
g.reset(); handleState();
g.clearRect(0, 0, g.getWidth(), g.getHeight()); handleAlarm();
// Draw again // Clear watch face
g.setColor(1,1,1); g.reset();
g.clearRect(0, 0, g.getWidth(), g.getHeight());
drawBackground(); // Draw again
drawLock(); g.setColor(1,1,1);
drawDate();
drawData();
drawTime();
// Queue draw in one minute drawBackground();
queueDraw(); drawLock();
drawDate();
drawState();
drawData();
drawTime();
// Queue draw in one minute
queueDraw();
} }
@ -208,12 +265,12 @@ function draw(){
* Listeners * Listeners
*/ */
Bangle.on('lcdPower',on=>{ Bangle.on('lcdPower',on=>{
if (on) { if (on) {
draw(); draw();
} else { // stop draw timer } else { // stop draw timer
if (drawTimeout) clearTimeout(drawTimeout); if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined; drawTimeout = undefined;
} }
}); });
Bangle.on('charging',function(charging) { Bangle.on('charging',function(charging) {
@ -224,6 +281,25 @@ Bangle.on('lock', function(isLocked) {
drawLock(); drawLock();
}); });
Bangle.on('touch', function(btn, e){
var upper = parseInt(g.getHeight() * 0.2);
var lower = g.getHeight() - upper;
var is_upper = e.y < upper;
var is_lower = e.y > lower;
if(is_upper){
feedback();
increaseAlarm();
draw();
}
if(is_lower){
feedback();
decreaseAlarm();
draw();
}
});
/* /*
@ -238,6 +314,74 @@ function queueDraw() {
} }
/*
* Handle alarm
*/
function getCurrentTimeInMinutes(){
return Math.floor(Date.now() / (1000*60));
}
function isAlarmEnabled(){
return settings.alarm >= 0;
}
function getAlarmMinutes(){
var currentTime = getCurrentTimeInMinutes();
return settings.alarm - currentTime;
}
function handleAlarm(){
if(!isAlarmEnabled()){
return;
}
if(getAlarmMinutes() > 0){
return;
}
// Alarm
var t = 300;
Bangle.buzz(t, 1)
.then(() => new Promise(resolve => setTimeout(resolve, t)))
.then(() => Bangle.buzz(t, 1))
.then(() => new Promise(resolve => setTimeout(resolve, t)))
.then(() => Bangle.buzz(t, 1))
.then(() => new Promise(resolve => setTimeout(resolve, t)))
.then(() => Bangle.buzz(t, 1))
.then(() => new Promise(resolve => setTimeout(resolve, 5E3)))
.then(() => {
// Update alarm state to disabled
settings.alarm = -1;
storage.writeJSON(SETTINGS_FILE, settings);
});
}
function increaseAlarm(){
if(isAlarmEnabled()){
settings.alarm += 5;
} else {
settings.alarm = getCurrentTimeInMinutes() + 5;
}
storage.writeJSON(SETTINGS_FILE, settings);
}
function decreaseAlarm(){
if(isAlarmEnabled() && (settings.alarm-5 > getCurrentTimeInMinutes())){
settings.alarm -= 5;
} else {
settings.alarm = -1;
}
storage.writeJSON(SETTINGS_FILE, settings);
}
function feedback(){
Bangle.buzz(40, 0.3);
}
/* /*
* Lets start widgets, listen for btn etc. * Lets start widgets, listen for btn etc.
*/ */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB