Add alarms app (fix #83)

pull/103/head
Gordon Williams 2020-02-12 10:48:14 +00:00
parent d8c3b73334
commit 47205bfe61
11 changed files with 224 additions and 4 deletions

View File

@ -2,7 +2,7 @@
{ "id": "boot",
"name": "Bootloader",
"icon": "bootloader.png",
"version":"0.03",
"version":"0.04",
"description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings",
"tags": "tool,system",
"storage": [
@ -13,7 +13,7 @@
"sortorder" : -10
},
{ "id": "launch",
"name": "Launcher",
"name": "Default Launcher",
"icon": "app.png",
"version":"0.01",
"description": "This is needed by Bangle.js to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.",
@ -66,6 +66,20 @@
],
"sortorder" : -2
},
{ "id": "alarm",
"name": "Default Alarm",
"icon": "app.png",
"version":"0.01",
"description": "Set and respond to alarms",
"tags": "tool,alarm",
"storage": [
{"name":"+alarm","url":"app.json"},
{"name":"-alarm","url":"app.js"},
{"name":"@alarm","content":"[]"},
{"name":"*alarm","url":"app-icon.js","evaluate":true},
{"name":"=alarm","url":"widget.js"}
]
},
{ "id": "wclock",
"name": "Word Clock",
"icon": "clock-word.png",

1
apps/alarm/ChangeLog Normal file
View File

@ -0,0 +1 @@
0.01: New App!

1
apps/alarm/app-icon.js Normal file
View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwkGswAhiMRCCAREAo4eHBIQLEAgwYHsIJDiwHB5gACBpIhHCoYZEGA4gFCw4ABGA4HEjgXJ4IXGAwcUB4VEmf//8zogICoJIFAodMBoNDCoIADmgJB4gXIFwXDCwoABngwFC4guB4k/CQXwh4EC+YMCC44iBp4qDC4n/+gNBC41sEIJCEC4v/GAPGC4dhXYRdFC4xhCCYIXCdQRdDC5HzegQXCsxGHC45IDCwQXCUgwXHJAIXGRogXJSIIXcOw4XIPAYXcBwv/mEDBAwXOgtQC65QGC5vzoEAJAx3Nmk/mEABIiPN+dDAQIwFC4zXGFwKRCGAjvMFwQECGAgXI4YuGGAUvAgU8C4/EFwwGCAgdMC4p4EFwobFOwoXDJAIoEAApGBC4xIEABJGHGAapEAAqNBFwwXD4heI+YuBC5BIBVQhdHIw4wD5inFS4IKCCxFmigNCokzCoMzogICoIWIsMRjgPCAA3BiMWC48RBQIXJEgMRFxAJCCw4lEC44IECooOIBAaBJKwhgIAH4ACA=="))

151
apps/alarm/app.js Normal file
View File

@ -0,0 +1,151 @@
Bangle.loadWidgets();
Bangle.drawWidgets();
var alarms = require("Storage").readJSON("@alarm")||[];
/*alarms = [
{ on : true,
hr : 6.5, // hours + minutes/60
msg : "Eat chocolate",
last : 0, // last day of the month we alarmed on - so we don't alarm twice in one day!
rp : true, // repeat
}
];*/
function formatTime(t) {
var hrs = 0|t;
var mins = 0|((t-hrs)*60);
return hrs+":"+("0"+mins).substr(-2);
}
function getCurrentHr() {
var time = new Date();
return time.getHours()+(time.getMinutes()/60);
}
function showMainMenu() {
const menu = {
'': { 'title': 'Alarms' },
'New Alarm': ()=>editAlarm(-1)
};
alarms.forEach((alarm,idx)=>{
txt = (alarm.on?"on ":"off ")+formatTime(alarm.hr);
if (alarm.rp) txt += " (repeat)";
menu[txt] = function() {
editAlarm(idx);
};
});
menu['< Back'] = ()=>{load();};
return E.showMenu(menu);
}
function editAlarm(alarmIndex) {
var newAlarm = alarmIndex<0;
var hrs = 12;
var mins = 0;
var en = true;
var repeat = true;
if (!newAlarm) {
var a = alarms[alarmIndex];
hrs = 0|a.hr;
mins = 0|((a.hr-hrs)*60);
en = a.on;
repeat = a.rp;
}
const menu = {
'': { 'title': 'Alarms' },
'Hours': {
value: hrs,
min: 0,
max: 23,
onchange: v=>hrs=v
},
'Minutes': {
value: mins,
min: 0,
max: 60,
onchange: v=>mins=v
},
'Enabled': {
value: en,
format: v=>v?"On":"Off",
onchange: v=>en=v
},
'Repeat': {
value: en,
format: v=>v?"Yes":"No",
onchange: v=>repeat=v
}
};
function getAlarm() {
var hr = hrs+(mins/60);
var day = 0;
// If alarm is for tomorrow not today, set day
if (hr > getCurrentHr())
day = (new Date()).getDate();
// Save alarm
return {
on : en, hr : hr,
last : day, rp : repeat
};
}
if (newAlarm) {
menu["> New Alarm"] = function() {
alarms.push(getAlarm());
require("Storage").write("@alarm",JSON.stringify(alarms));
showMainMenu();
};
} else {
menu["> Save"] = function() {
alarms[alarmIndex] = getAlarm();
require("Storage").write("@alarm",JSON.stringify(alarms));
showMainMenu();
};
}
menu['< Back'] = showMainMenu;
return E.showMenu(menu);
}
function showAlarm(alarm) {
var msg = formatTime(alarm.hr);
var buzzCount = 10;
if (alarm.msg)
msg += "\n"+alarm.msg;
E.showPrompt(msg,{
title:"ALARM!",
buttons : {"Sleep":true,"Ok":false} // default is sleep so it'll come back in 10 mins
}).then(function(sleep) {
buzzCount = 0;
if (sleep) {
alarm.hr += 10/60; // 10 minutes
} else {
alarm.last = (new Date()).getDate();
if (!alarm.rp) alarm.on = false;
}
require("Storage").write("@alarm",JSON.stringify(alarms));
load();
});
function buzz() {
Bangle.buzz(100).then(()=>{
setTimeout(()=>{
Bangle.buzz(100).then(function() {
if (buzzCount--)
setTimeout(buzz, 3000);
});
},100);
});
}
buzz();
}
// Check for alarms
var day = (new Date()).getDate();
var hr = getCurrentHr();
var active = alarms.filter(a=>a.on&&(a.hr<hr)&&(a.last!=day));
if (active.length) {
// if there's an alarm, show it
active = active.sort((a,b)=>a.hr-b.hr);
showAlarm(active[0]);
} else {
// otherwise show the main menu
showMainMenu();
}

5
apps/alarm/app.json Normal file
View File

@ -0,0 +1,5 @@
{
"name":"Alarms",
"icon":"*alarm",
"src":"-alarm"
}

BIN
apps/alarm/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

17
apps/alarm/widget.js Normal file
View File

@ -0,0 +1,17 @@
(() => {
var alarms = require('Storage').readJSON('@alarm')||[];
alarms = alarms.filter(alarm=>alarm.on);
if (!alarms.length) return;
delete alarms;
// add the width
var xpos = WIDGETPOS.tl;
WIDGETPOS.tl += 24;/* the widget width plus some extra pixel to keep distance to others */;
// draw your widget at xpos
// add the widget
WIDGETS["alarm"]={draw:function() {
g.setColor(-1);
g.drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),xpos,0);
}};
})()

View File

@ -1,2 +1,3 @@
0.02: Attempt to reset state of the interpreter better before loading an app
0.03: Fix issue switching clockfaces via menu
0.04: Add alarm functionality

View File

@ -19,6 +19,30 @@ Bangle.setLCDTimeout(s.timeout);
if (!s.timeout) Bangle.setLCDPower(1);
E.setTimeZone(s.timezone);
delete s;
// check for alarms
function checkAlarm() {
var alarms = require('Storage').readJSON('@alarm')||[];
var time = new Date();
var active = alarms.filter(a=>a.on&&(a.last!=time.getDate()));
if (active.length) {
active = active.sort((a,b)=>a.hr-b.hr);
var hr = time.getHours()+(time.getMinutes()/60);
if (!require('Storage').read("-alarm")) {
console.log("No alarm app!");
require('Storage').write('@alarm',"[]")
} else {
if (active[0].hr < hr) {
// fire alarm now
load("-alarm");
} else {
// execute alarm at the correct time
setTimeout(function() {
load("-alarm");
},3600000*(active[0].hr-hr));
}
}
}
}
// check to see if our clock is wrong - if it is use GPS time
if ((new Date()).getFullYear()==1970) {
console.log("Searching for GPS time");
@ -32,9 +56,12 @@ if ((new Date()).getFullYear()==1970) {
}
setTime(g.time.getTime()/1000);
console.log("GPS time",g.time.toString());
checkAlarm();
});
Bangle.setGPSPower(1);
}
} else checkAlarm();
delete checkAlarm;
// Check for
// All of this is just shim for older Bangles
if (!Bangle.loadWidgets) {
Bangle.loadWidgets = function(){

View File

@ -1,3 +1,6 @@
Bangle.loadWidgets();
Bangle.drawWidgets();
const storage = require('Storage');
let settings;

View File

@ -1 +1 @@
["boot","launch","mclock","setting","sbat","sbt"]
["boot","launch","mclock","setting","alarm","sbat","sbt"]