forked from FOSS/BangleApps
Refactored alarm into separate 'sched' library/app
parent
30e94e15ad
commit
5c84ec9e2c
|
@ -15,3 +15,4 @@
|
|||
0.14: Order of 'back' menu item
|
||||
0.15: Fix hour/minute wrapping code for new menu system
|
||||
0.16: Adding alarm library
|
||||
0.17: Moving alarm internals to 'sched' library
|
||||
|
|
|
@ -1,82 +1,6 @@
|
|||
Default Alarm & Timer
|
||||
======================
|
||||
|
||||
This provides an app, widget, library and tools for alarms and timers.
|
||||
This allows you to add/modify any running timers.
|
||||
|
||||
Other apps can use this to provide alarm functionality.
|
||||
|
||||
App
|
||||
---
|
||||
|
||||
The Alarm app allows you to add/modify any running timers.
|
||||
|
||||
|
||||
Internals / Library
|
||||
-------------------
|
||||
|
||||
Alarms are stored in an array in `alarm.json`, and take the form:
|
||||
|
||||
```
|
||||
{
|
||||
id : "mytimer", // optional ID for this alarm/timer, so apps can easily find *their* timers
|
||||
on : true, // is the alarm enabled?
|
||||
t : 23400000, // Time of day since midnight in ms (if a timer, this is set automatically when timer starts)
|
||||
dow : 0b1111111, // Binary encoding for days of the week to run alarm on
|
||||
// SUN = 1
|
||||
// MON = 2
|
||||
// TUE = 4
|
||||
// WED = 8
|
||||
// THU = 16
|
||||
// FRI = 32
|
||||
// SAT = 64
|
||||
msg : "Eat chocolate", // message to display
|
||||
last : 0, // last day of the month we alarmed on - so we don't alarm twice in one day!
|
||||
rp : true, // repeat
|
||||
vibrate : "...", // pattern of '.', '-' and ' ' to use for when buzzing out this alarm (defaults to '..' if not set)
|
||||
as : false, // auto snooze
|
||||
timer : 5*60*1000, // OPTIONAL - if set, this is a timer and it's the time in ms
|
||||
js : "load('myapp.js')" // OPTIONAL - a JS command to execute when the alarm activates (*instead* of loading 'alarm.js')
|
||||
// when this code is run, you're responsible for setting alarm.on=false (or removing the alarm)
|
||||
data : { ... } // OPTIONAL - your app can store custom data in here if needed
|
||||
}
|
||||
```
|
||||
|
||||
You app
|
||||
|
||||
The [`alarm` library](https://github.com/espruino/BangleApps/blob/master/apps/alarm/lib.js) contains
|
||||
a few helpful functions for getting/setting alarms, but is intentionally sparse so as not to
|
||||
use too much RAM.
|
||||
|
||||
It can be used as follows:
|
||||
|
||||
```
|
||||
// add/update an existing alarm
|
||||
require("alarm").setAlarm("mytimer", {
|
||||
msg : "Wake up",
|
||||
timer : 10*60*1000, // 10 Minutes
|
||||
});
|
||||
// Ensure the widget and alarm timer updates to schedule the new alarm properly
|
||||
require("alarm").reload();
|
||||
|
||||
// Get the time to the next alarm for us
|
||||
var timeToNext = require("alarm").getTimeToAlarm(require("alarm").getAlarm("mytimer"));
|
||||
// timeToNext===undefined if no alarm or alarm disabled
|
||||
|
||||
// delete an alarm
|
||||
require("alarm").setAlarm("mytimer", undefined);
|
||||
// reload after deleting...
|
||||
require("alarm").reload();
|
||||
|
||||
// Or add an alarm that runs your own code - in this case
|
||||
// loading the settings app. The alarm will not be removed/stopped
|
||||
// automatically.
|
||||
require("alarm").setAlarm("customrunner", {
|
||||
js : "load('setting.app.js')",
|
||||
timer : 1*60*1000, // 1 Minute
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
|
||||
If your app requires alarms, you can specify that the alarms app needs to
|
||||
be installed by adding `"dependencies": {"alarm":"app"},` to your metadata.
|
||||
It uses the [`sched` library](https://github.com/espruino/BangleApps/blob/master/apps/sched) to handle the alarm scheduling in an efficient way that can work alongside other apps.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
var alarms = require("Storage").readJSON("alarm.json",1)||[];
|
||||
var alarms = require("Storage").readJSON("sched.json",1)||[];
|
||||
// An array of alarm objects (see README.md)
|
||||
|
||||
// time in ms -> { hrs, mins }
|
||||
|
@ -31,8 +31,8 @@ function getCurrentTime() {
|
|||
}
|
||||
|
||||
function saveAndReload() {
|
||||
require("Storage").write("alarm.json",JSON.stringify(alarms));
|
||||
require("alarm").reload();
|
||||
require("Storage").write("sched.json",JSON.stringify(alarms));
|
||||
require("sched").reload();
|
||||
}
|
||||
|
||||
function showMainMenu() {
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
// check for alarms
|
||||
(function() {
|
||||
if (Bangle.ALARM) {
|
||||
clearTimeout(Bangle.ALARM);
|
||||
delete Bangle.ALARM;
|
||||
}
|
||||
var alarms = require('Storage').readJSON('alarm.json',1)||[];
|
||||
var time = new Date();
|
||||
var active = alarms.filter(a=>a.on && (a.dow>>time.getDay())&1);
|
||||
if (active.length) {
|
||||
active = active.sort((a,b)=>(a.t-b.t)+(a.last-b.last)*86400000);
|
||||
var currentTime = (time.getHours()*3600000)+(time.getMinutes()*60000)+(time.getSeconds()*1000);
|
||||
if (!require('Storage').read("alarm.js")) {
|
||||
console.log("No alarm app!");
|
||||
require('Storage').write('alarm.json',"[]");
|
||||
} else {
|
||||
var t = active[0].t-currentTime;
|
||||
if (active[0].last == time.getDate() || t < -60000) t += 86400000;
|
||||
if (t<1000) t=1000; // start alarm min 1 sec from now
|
||||
/* execute alarm at the correct time. We avoid execing immediately
|
||||
since this code will get called AGAIN when alarm.js is loaded. alarm.js
|
||||
will then clearInterval() to get rid of this call so it can proceed
|
||||
normally.
|
||||
If active[0].js is defined, just run that code as-is and not alarm.js */
|
||||
Bangle.ALARM = setTimeout(active[0].js||'load("alarm.js")',t);
|
||||
}
|
||||
} else { // check for new alarms at midnight (so day of week works)
|
||||
Bangle.ALARM = setTimeout(() => {
|
||||
eval(require("Storage").read("alarm.boot.js"));
|
||||
}, 86400000 - (Date.now()%86400000));
|
||||
}
|
||||
})();
|
|
@ -1,20 +1,17 @@
|
|||
{
|
||||
"id": "alarm",
|
||||
"name": "Default Alarm & Timer",
|
||||
"name": "Alarm & Timer",
|
||||
"shortName": "Alarms",
|
||||
"version": "0.16",
|
||||
"version": "0.17",
|
||||
"description": "Set and respond to alarms and timers",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,alarm,widget",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"dependencies": {"scheduler":"type"},
|
||||
"storage": [
|
||||
{"name":"alarm.app.js","url":"app.js"},
|
||||
{"name":"alarm.boot.js","url":"boot.js"},
|
||||
{"name":"alarm.js","url":"alarm.js"},
|
||||
{"name":"alarm.img","url":"app-icon.js","evaluate":true},
|
||||
{"name":"alarm.wid.js","url":"widget.js"},
|
||||
{"name":"alarm","url":"lib.js"}
|
||||
],
|
||||
"data": [{"name":"alarm.json"}]
|
||||
{"name":"alarm.wid.js","url":"widget.js"}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ WIDGETS["alarm"]={area:"tl",width:0,draw:function() {
|
|||
if (this.width) g.reset().drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y);
|
||||
},reload:function() {
|
||||
// don't include library here as we're trying to use as little RAM as possible
|
||||
WIDGETS["alarm"].width = (require('Storage').readJSON('alarm.json',1)||[]).some(alarm=>alarm.on) ? 24 : 0;
|
||||
WIDGETS["alarm"].width = (require('Storage').readJSON('sched.json',1)||[]).some(alarm=>alarm.on&&(alarm.hidden!==false)) ? 24 : 0;
|
||||
}
|
||||
};
|
||||
WIDGETS["alarm"].reload();
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
|
@ -0,0 +1,82 @@
|
|||
Sched: Scheduling library for alarms and timers
|
||||
====================================
|
||||
|
||||
This provides boot code, a library and tools for alarms and timers.
|
||||
|
||||
Other apps can use this to provide alarm functionality.
|
||||
|
||||
App
|
||||
---
|
||||
|
||||
The Alarm app allows you to add/modify any running timers.
|
||||
|
||||
|
||||
Internals / Library
|
||||
-------------------
|
||||
|
||||
Alarms are stored in an array in `sched.json`, and take the form:
|
||||
|
||||
```
|
||||
{
|
||||
id : "mytimer", // optional ID for this alarm/timer, so apps can easily find *their* timers
|
||||
on : true, // is the alarm enabled?
|
||||
t : 23400000, // Time of day since midnight in ms (if a timer, this is set automatically when timer starts)
|
||||
dow : 0b1111111, // Binary encoding for days of the week to run alarm on
|
||||
// SUN = 1
|
||||
// MON = 2
|
||||
// TUE = 4
|
||||
// WED = 8
|
||||
// THU = 16
|
||||
// FRI = 32
|
||||
// SAT = 64
|
||||
|
||||
date : "2022-04-04", // OPTIONAL date for the alarm, in YYYY-MM-DD format
|
||||
// eg (new Date()).toISOString().substr(0,10)
|
||||
msg : "Eat food", // message to display
|
||||
last : 0, // last day of the month we alarmed on - so we don't alarm twice in one day!
|
||||
rp : true, // repeat the alarm every day?
|
||||
vibrate : "...", // OPTIONAL pattern of '.', '-' and ' ' to use for when buzzing out this alarm (defaults to '..' if not set)
|
||||
hidden : false, // OPTIONAL if false, the widget should not show an icon for this alarm
|
||||
as : false, // auto snooze
|
||||
timer : 5*60*1000, // OPTIONAL - if set, this is a timer and it's the time in ms
|
||||
js : "load('myapp.js')" // OPTIONAL - a JS command to execute when the alarm activates (*instead* of loading 'sched.js')
|
||||
// when this code is run, you're responsible for setting alarm.on=false (or removing the alarm)
|
||||
data : { ... } // OPTIONAL - your app can store custom data in here if needed
|
||||
}
|
||||
```
|
||||
|
||||
The [`sched` library](https://github.com/espruino/BangleApps/blob/master/apps/sched/lib.js) contains
|
||||
a few helpful functions for getting/setting alarms and timers, but is intentionally sparse so as not to
|
||||
use too much RAM.
|
||||
|
||||
It can be used as follows:
|
||||
|
||||
```
|
||||
// add/update an existing alarm
|
||||
require("sched").setAlarm("mytimer", {
|
||||
msg : "Wake up",
|
||||
timer : 10*60*1000, // 10 Minutes
|
||||
});
|
||||
// Ensure the widget and alarm timer updates to schedule the new alarm properly
|
||||
require("sched").reload();
|
||||
|
||||
// Get the time to the next alarm for us
|
||||
var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm("mytimer"));
|
||||
// timeToNext===undefined if no alarm or alarm disabled
|
||||
|
||||
// delete an alarm
|
||||
require("sched").setAlarm("mytimer", undefined);
|
||||
// reload after deleting...
|
||||
require("sched").reload();
|
||||
|
||||
// Or add an alarm that runs your own code - in this case
|
||||
// loading the settings app. The alarm will not be removed/stopped
|
||||
// automatically.
|
||||
require("sched").setAlarm("customrunner", {
|
||||
js : "load('setting.app.js')",
|
||||
timer : 1*60*1000, // 1 Minute
|
||||
});
|
||||
```
|
||||
|
||||
If your app requires alarms, you can specify that the alarms app needs to
|
||||
be installed by adding `"dependencies": {"scheduler":"type"},` to your metadata.
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwkGswAhiMRCCAREAo4eHBIQLEAgwYHsIJDiwHB5gACBpIhHCoYZEGA4gFCw4ABGA4HEjgXJ4IXGAwcUB4VEmf//8zogICoJIFAodMBoNDCoIADmgJB4gXIFwXDCwoABngwFC4guB4k/CQXwh4EC+YMCC44iBp4qDC4n/+gNBC41sEIJCEC4v/GAPGC4dhXYRdFC4xhCCYIXCdQRdDC5HzegQXCsxGHC45IDCwQXCUgwXHJAIXGRogXJSIIXcOw4XIPAYXcBwv/mEDBAwXOgtQC65QGC5vzoEAJAx3Nmk/mEABIiPN+dDAQIwFC4zXGFwKRCGAjvMFwQECGAgXI4YuGGAUvAgU8C4/EFwwGCAgdMC4p4EFwobFOwoXDJAIoEAApGBC4xIEABJGHGAapEAAqNBFwwXD4heI+YuBC5BIBVQhdHIw4wD5inFS4IKCCxFmigNCokzCoMzogICoIWIsMRjgPCAA3BiMWC48RBQIXJEgMRFxAJCCw4lEC44IECooOIBAaBJKwhgIAH4ACA=="))
|
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,27 @@
|
|||
// check for alarms
|
||||
(function() {
|
||||
if (Bangle.ALARM) {
|
||||
clearTimeout(Bangle.ALARM);
|
||||
delete Bangle.ALARM;
|
||||
}
|
||||
var alarms = require('Storage').readJSON('sched.json',1)||[];
|
||||
var time = new Date();
|
||||
var active = alarms.filter(a=>a.on && (a.dow>>time.getDay())&1 && (!a.date || a.date==time.toISOString().substr(0,10)));
|
||||
if (active.length) {
|
||||
active = active.sort((a,b)=>(a.t-b.t)+(a.last-b.last)*86400000);
|
||||
var currentTime = (time.getHours()*3600000)+(time.getMinutes()*60000)+(time.getSeconds()*1000);
|
||||
var t = active[0].t-currentTime;
|
||||
if (active[0].last == time.getDate() || t < -60000) t += 86400000;
|
||||
if (t<1000) t=1000; // start alarm min 1 sec from now
|
||||
/* execute alarm at the correct time. We avoid execing immediately
|
||||
since this code will get called AGAIN when alarm.js is loaded. alarm.js
|
||||
will then clearInterval() to get rid of this call so it can proceed
|
||||
normally.
|
||||
If active[0].js is defined, just run that code as-is and not alarm.js */
|
||||
Bangle.ALARM = setTimeout(active[0].js||'load("sched.js")',t);
|
||||
} else { // check for new alarms at midnight (so day of week works)
|
||||
Bangle.ALARM = setTimeout(() => {
|
||||
eval(require("Storage").read("sched.boot.js"));
|
||||
}, 86400000 - (Date.now()%86400000));
|
||||
}
|
||||
})();
|
|
@ -1,15 +1,15 @@
|
|||
// Return an array of all alarms
|
||||
exports.getAlarms = function() {
|
||||
return require("Storage").readJSON("alarm.json",1)||[];
|
||||
return require("Storage").readJSON("sched.json",1)||[];
|
||||
};
|
||||
// Return an alarm object based on ID
|
||||
exports.getAlarm = function(id) {
|
||||
var alarms = require("Storage").readJSON("alarm.json",1)||[];
|
||||
var alarms = require("Storage").readJSON("sched.json",1)||[];
|
||||
return alarms.find(a=>a.id==id);
|
||||
};
|
||||
// Set an alarm object based on ID. Leave 'alarm' undefined to remove it
|
||||
exports.setAlarm = function(id, alarm) {
|
||||
var alarms = require("Storage").readJSON("alarm.json",1)||[];
|
||||
var alarms = require("Storage").readJSON("sched.json",1)||[];
|
||||
alarms = alarms.filter(a=>a.id!=id);
|
||||
if (alarm !== undefined) {
|
||||
alarm.id = id;
|
||||
|
@ -22,13 +22,13 @@ exports.setAlarm = function(id, alarm) {
|
|||
}
|
||||
}
|
||||
alarms.push(alarm);
|
||||
require("Storage").writeJSON("alarm.json", alarms);
|
||||
require("Storage").writeJSON("sched.json", alarms);
|
||||
};
|
||||
/// Get time until the given alarm (object). Return undefined if alarm not enabled, or if 86400000 or more, alarm could me *more* than a day in the future
|
||||
exports.getTimeToAlarm = function(alarm, time) {
|
||||
if (!alarm) return undefined;
|
||||
if (!time) time = new Date();
|
||||
var active = alarm.on && (alarm.dow>>time.getDay())&1;
|
||||
var active = alarm.on && (alarm.dow>>time.getDay())&1 && (!alarm.date || alarm.date==time.toISOString().substr(0,10));
|
||||
if (!active) return undefined;
|
||||
var currentTime = (time.getHours()*3600000)+(time.getMinutes()*60000)+(time.getSeconds()*1000);
|
||||
var t = alarm.t-currentTime;
|
||||
|
@ -37,7 +37,7 @@ exports.getTimeToAlarm = function(alarm, time) {
|
|||
};
|
||||
/// Force a reload of the current alarms and widget
|
||||
exports.reload = function() {
|
||||
eval(require("Storage").read("alarm.boot.js"));
|
||||
eval(require("Storage").read("sched.boot.js"));
|
||||
if (WIDGETS["alarm"]) {
|
||||
WIDGETS["alarm"].reload();
|
||||
Bangle.drawWidgets();
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"id": "sched",
|
||||
"name": "Scheduler",
|
||||
"version": "0.01",
|
||||
"description": "Scheduling library for alarms and timers",
|
||||
"icon": "app.png",
|
||||
"type": "scheduler",
|
||||
"tags": "tool,system,alarm",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"sched.boot.js","url":"boot.js"},
|
||||
{"name":"sched.js","url":"sched.js"},
|
||||
{"name":"sched.img","url":"app-icon.js","evaluate":true},
|
||||
{"name":"sched","url":"lib.js"}
|
||||
],
|
||||
"data": [{"name":"sched.json"}]
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// Chances are boot0.js got run already and scheduled *another*
|
||||
// 'load(alarm.js)' - so let's remove it first!
|
||||
// 'load(sched.js)' - so let's remove it first!
|
||||
if (Bangle.ALARM) {
|
||||
clearInterval(Bangle.ALARM);
|
||||
delete Bangle.ALARM;
|
||||
|
@ -54,7 +54,7 @@ function showAlarm(alarm) {
|
|||
}
|
||||
if (!alarm.rp) alarm.on = false;
|
||||
}
|
||||
require("Storage").write("alarm.json",JSON.stringify(alarms));
|
||||
require("Storage").write("sched.json",JSON.stringify(alarms));
|
||||
load();
|
||||
});
|
||||
function buzz() {
|
||||
|
@ -74,8 +74,8 @@ function showAlarm(alarm) {
|
|||
// Check for alarms
|
||||
var day = (new Date()).getDate();
|
||||
var currentTime = getCurrentTime()+10000; // get current time - 10s in future to ensure we alarm if we've started the app a tad early
|
||||
var alarms = require("Storage").readJSON("alarm.json",1)||[];
|
||||
var active = alarms.filter(a=>a.on&&(a.t<currentTime)&&(a.last!=day));
|
||||
var alarms = require("Storage").readJSON("sched.json",1)||[];
|
||||
var active = alarms.filter(a=>a.on&&(a.t<currentTime)&&(a.last!=day) && (!a.date || a.date==time.toISOString().substr(0,10)));
|
||||
if (active.length) {
|
||||
// if there's an alarm, show it
|
||||
active = active.sort((a,b)=>a.t-b.t);
|
Loading…
Reference in New Issue