Merge pull request #1707 from alessandrococco/sched-unlock-display-at-buzz

[Scheduler] New functions & Settings page
master
Gordon Williams 2022-04-20 13:46:13 +01:00 committed by GitHub
commit c214f47313
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 221 additions and 73 deletions

View File

@ -18,3 +18,4 @@
0.17: Moving alarm internals to 'sched' library
0.18: Cope with >1 identical alarm at once (#1667)
0.19: Ensure rescheduled alarms that already fired have 'last' reset
0.20: Use the new 'sched' factories to initialize new alarms/timers

View File

@ -1,28 +1,28 @@
Bangle.loadWidgets();
Bangle.drawWidgets();
var alarms = require("sched").getAlarms();
// An array of alarm objects (see sched/README.md)
let alarms = require("sched").getAlarms();
// time in ms -> { hrs, mins }
function decodeTime(t) {
t = 0|t; // sanitise
var hrs = 0|(t/3600000);
return { hrs : hrs, mins : Math.round((t-hrs*3600000)/60000) };
t = 0 | t; // sanitise
let hrs = 0 | (t / 3600000);
return { hrs: hrs, mins: Math.round((t - hrs * 3600000) / 60000) };
}
// time in { hrs, mins } -> ms
function encodeTime(o) {
return o.hrs*3600000 + o.mins*60000;
return o.hrs * 3600000 + o.mins * 60000;
}
function formatTime(t) {
var o = decodeTime(t);
return o.hrs+":"+("0"+o.mins).substr(-2);
let o = decodeTime(t);
return o.hrs + ":" + ("0" + o.mins).substr(-2);
}
function getCurrentTime() {
var time = new Date();
let time = new Date();
return (
time.getHours() * 3600000 +
time.getMinutes() * 60000 +
@ -39,7 +39,7 @@ function showMainMenu() {
// Timer img "\0"+atob("DhKBAP////MDDAwwMGGBzgPwB4AeAPwHOBhgwMMzDez////w")
// Alarm img "\0"+atob("FBSBAABgA4YcMPDGP8Zn/mx/48//PP/zD/8A//AP/wD/8A//AP/wH/+D//w//8AAAADwAAYA")
const menu = {
'': { 'title': 'Alarm/Timer' },
'': { 'title': /*LANG*/'Alarms&Timers' },
/*LANG*/'< Back' : ()=>{load();},
/*LANG*/'New Alarm': ()=>editAlarm(-1),
/*LANG*/'New Timer': ()=>editTimer(-1)
@ -76,13 +76,13 @@ function showMainMenu() {
function editDOW(dow, onchange) {
const menu = {
'': { 'title': /*LANG*/'Days of Week' },
'< Back' : () => onchange(dow)
/*LANG*/'< Back' : () => onchange(dow)
};
for (var i = 0; i < 7; i++) (i => {
var dayOfWeek = require("locale").dow({ getDay: () => i });
for (let i = 0; i < 7; i++) (i => {
let dayOfWeek = require("locale").dow({ getDay: () => i });
menu[dayOfWeek] = {
value: !!(dow&(1<<i)),
format: v => v ? "Yes" : "No",
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
onchange: v => v ? dow |= 1<<i : dow &= ~(1<<i),
};
})(i);
@ -90,23 +90,15 @@ function editDOW(dow, onchange) {
}
function editAlarm(alarmIndex, alarm) {
var newAlarm = alarmIndex<0;
var a = {
t : 12*3600000, // 12 o clock default
on : true,
rp : false, // repeat not the default
as : false,
dow : 0b1111111,
last : 0,
vibrate : ".."
}
let newAlarm = alarmIndex < 0;
let a = require("sched").newDefaultAlarm();
if (!newAlarm) Object.assign(a, alarms[alarmIndex]);
if (alarm) Object.assign(a,alarm);
var t = decodeTime(a.t);
let t = decodeTime(a.t);
const menu = {
'': { 'title': /*LANG*/'Alarm' },
'< Back' : () => showMainMenu(),
/*LANG*/'< Back' : () => showMainMenu(),
/*LANG*/'Hours': {
value: t.hrs, min : 0, max : 23, wrap : true,
onchange: v => t.hrs=v
@ -117,23 +109,23 @@ function editAlarm(alarmIndex, alarm) {
},
/*LANG*/'Enabled': {
value: a.on,
format: v=>v?"On":"Off",
format: v => v ? /*LANG*/"On" : /*LANG*/"Off",
onchange: v=>a.on=v
},
/*LANG*/'Repeat': {
value: a.rp,
format: v=>v?"Yes":"No",
onchange: v=>a.rp=v
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
onchange: v => a.rp = v
},
/*LANG*/'Days': {
value: "SMTWTFS".split("").map((d,n)=>a.dow&(1<<n)?d:".").join(""),
onchange: () => editDOW(a.dow, d=>{a.dow=d;editAlarm(alarmIndex,a)})
},
/*LANG*/'Vibrate': require("buzz_menu").pattern(a.vibrate, v => a.vibrate=v ),
/*LANG*/'Auto snooze': {
/*LANG*/'Auto Snooze': {
value: a.as,
format: v=>v?"Yes":"No",
onchange: v=>a.as=v
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
onchange: v => a.as = v
}
};
menu[/*LANG*/"Save"] = function() {
@ -155,23 +147,15 @@ function editAlarm(alarmIndex, alarm) {
}
function editTimer(alarmIndex, alarm) {
var newAlarm = alarmIndex<0;
var a = {
timer : 5*60*1000, // 5 minutes
on : true,
rp : false,
as : false,
dow : 0b1111111,
last : 0,
vibrate : ".."
}
let newAlarm = alarmIndex < 0;
let a = require("sched").newDefaultTimer();
if (!newAlarm) Object.assign(a, alarms[alarmIndex]);
if (alarm) Object.assign(a,alarm);
var t = decodeTime(a.timer);
let t = decodeTime(a.timer);
const menu = {
'': { 'title': /*LANG*/'Timer' },
'< Back' : () => showMainMenu(),
/*LANG*/'< Back' : () => showMainMenu(),
/*LANG*/'Hours': {
value: t.hrs, min : 0, max : 23, wrap : true,
onchange: v => t.hrs=v
@ -182,8 +166,8 @@ function editTimer(alarmIndex, alarm) {
},
/*LANG*/'Enabled': {
value: a.on,
format: v=>v?"On":"Off",
onchange: v=>a.on=v
format: v => v ? /*LANG*/"On" : /*LANG*/"Off",
onchange: v => a.on = v
},
/*LANG*/'Vibrate': require("buzz_menu").pattern(a.vibrate, v => a.vibrate=v ),
};

View File

@ -1,8 +1,8 @@
{
"id": "alarm",
"name": "Alarm & Timer",
"name": "Alarms & Timers",
"shortName": "Alarms",
"version": "0.19",
"version": "0.20",
"description": "Set alarms and timers on your Bangle",
"icon": "app.png",
"tags": "tool,alarm,widget",

View File

@ -2,3 +2,4 @@
0.02: Fix scheduling of other alarms if there is a pending alarm from the past (fix #1667)
0.03: Fix `getTimeToAlarm` for a timer already used at same day, don't set `last` for timers.
0.04: Fix `getTimeToAlarm` to check for next dow if alarm.t lower currentTime.
0.05: Export new functions (`newDefaultAlarm/Timer`), add Settings page

View File

@ -8,8 +8,17 @@ Other apps can use this to provide alarm functionality.
App
---
The Alarm app allows you to add/modify any running timers.
The **Alarms & Timers** app allows you to add/modify any running alarms and timers.
Global Settings
---------------
- `Unlock at Buzz` - If `Yes` the alarm/timer will unlock the watch
- `Default Auto Snooze` - Default _Auto Snooze_ value for newly created alarms (_Alarms_ only)
- `Default Snooze` - Default _Snooze_ value for newly created alarms/timers
- `Buzz Count` - The number of buzzes before the watch goes silent
- `Buzz Interval` - The interval between one buzz and the next
- `Default Alarm/Timer Pattern` - Default vibration pattern for newly created alarms/timers
Internals / Library
-------------------
@ -53,21 +62,27 @@ use too much RAM.
It can be used as follows:
```
// add/update an existing alarm
// Get a new alarm with default values
let alarm = require("sched").newDefaultAlarm();
// Get a new timer with default values
let timer = require("sched").newDefaultTimer();
// Add/update an existing alarm
require("sched").setAlarm("mytimer", {
msg : "Wake up",
timer : 10*60*1000, // 10 Minutes
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
let timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm("mytimer"));
// timeToNext === undefined if no alarm or alarm disabled
// delete an alarm
// Delete an alarm
require("sched").setAlarm("mytimer", undefined);
// reload after deleting...
// Reload after deleting
require("sched").reload();
// Or add an alarm that runs your own code - in this case
@ -76,12 +91,15 @@ require("sched").reload();
require("sched").setAlarm("customrunner", {
appid : "myapp",
js : "load('setting.app.js')",
timer : 1*60*1000, // 1 Minute
timer : 1 * 60 * 1000 // 1 minute
});
// If you have been specifying `appid` you can also find any alarms that
// your app has created with the following:
require("sched").getAlarms().filter(a=>a.appid=="myapp");
require("sched").getAlarms().filter(a => a.appid == "myapp");
// Get the scheduler settings
let settings = require("sched").getSettings();
```
If your app requires alarms, you can specify that the alarms app needs to

View File

@ -52,3 +52,58 @@ exports.reload = function() {
Bangle.drawWidgets();
}
};
// Factory that creates a new alarm with default values
exports.newDefaultAlarm = function () {
const settings = exports.getSettings();
let alarm = {
t: 12 * 3600000, // Default to 12:00
on: true,
rp: false, // repeat not the default
as: settings.defaultAutoSnooze || false,
dow: 0b1111111,
last: 0,
vibrate: settings.defaultAlarmPattern,
};
delete settings;
return alarm;
}
// Factory that creates a new timer with default values
exports.newDefaultTimer = function () {
const settings = exports.getSettings();
let timer = {
timer: 5 * 60 * 1000, // 5 minutes
on: true,
rp: false,
as: false,
dow: 0b1111111,
last: 0,
vibrate: settings.defaultTimerPattern
}
delete settings;
return timer;
};
// Return the scheduler settings
exports.getSettings = function () {
return Object.assign(
{
unlockAtBuzz: false,
defaultSnoozeMillis: 600000, // 10 minutes
defaultAutoSnooze: false,
buzzCount: 10,
buzzIntervalMillis: 3000, // 3 seconds
defaultAlarmPattern: "..",
defaultTimerPattern: ".."
},
require("Storage").readJSON("sched.settings.json", true) || {}
);
}
// Write the updated settings back to storage
exports.setSettings = function(settings) {
require("Storage").writeJSON("sched.settings.json", settings);
};

View File

@ -1,7 +1,7 @@
{
"id": "sched",
"name": "Scheduler",
"version": "0.04",
"version": "0.05",
"description": "Scheduling library for alarms and timers",
"icon": "app.png",
"type": "scheduler",
@ -12,7 +12,8 @@
{"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"}
{"name":"sched","url":"lib.js"},
{"name":"sched.settings.js","url":"settings.js"}
],
"data": [{"name":"sched.json"}]
"data": [{"name":"sched.json"}, {"name":"sched.settings.json"}]
}

View File

@ -18,7 +18,9 @@ function formatTime(t) {
}
function showAlarm(alarm) {
var msg = "";
const settings = require("sched").getSettings();
let msg = "";
msg += alarm.timer ? formatTime(alarm.timer) : formatTime(alarm.t);
if (alarm.msg) {
msg += "\n"+alarm.msg;
@ -28,9 +30,12 @@ function showAlarm(alarm) {
else
msg = atob("AC0swgF97///RcEpMlVVVVVVf9VVVVVVVVX/9VVf9VVf/1VVV///1Vf9VX///VVX///VWqqlV///1Vf//9aqqqqpf//9V///2qqqqqqn///V///6qqqqqqr///X//+qqoAAKqqv//3//6qoAAAAKqr//3//qqAAAAAAqq//3/+qoAADwAAKqv/3/+qgAADwAACqv/3/aqAAADwAAAqp/19qoAAADwAAAKqfV1qgAAADwAAACqXVWqgAAADwAAACqlVWqAAAADwAAAAqlVWqAAAADwAAAAqlVWqAAAADwAAAAqlVaoAAAADwAAAAKpVaoAAAADwAAAAKpVaoAAAADwAAAAKpVaoAAAAOsAAAAKpVaoAAAAOsAAAAKpVaoAAAAL/AAAAKpVaoAAAAgPwAAAKpVaoAAACAD8AAAKpVWqAAAIAA/AAAqlVWqAAAgAAPwAAqlVWqAACAAADwAAqlVWqgAIAAAAAACqlVVqgAgAAAAAACqVVVqoAAAAAAAAKqVVVaqAAAAAAAAqpVVVWqgAAAAAACqlVVVWqoAAAAAAKqlVVVVqqAAAAAAqqVVVVVaqoAAAAKqpVVVVVeqqoAAKqqtVVVVV/6qqqqqqr/VVVVX/2qqqqqqn/1VVVf/VaqqqqpV/9VVVf9VVWqqlVVf9VVVf1VVVVVVVVX9VQ==")+" "+msg;
}
Bangle.loadWidgets();
Bangle.drawWidgets();
var buzzCount = 10;
let buzzCount = settings.buzzCount;
E.showPrompt(msg,{
title:alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!",
buttons : {/*LANG*/"Snooze":true,/*LANG*/"Ok":false} // default is sleep so it'll come back in 10 mins
@ -38,7 +43,7 @@ function showAlarm(alarm) {
buzzCount = 0;
if (sleep) {
if(alarm.ot===undefined) alarm.ot = alarm.t;
alarm.t += 10*60*1000; // 10 minutes
alarm.t += settings.defaultSnoozeMillis;
} else {
if (!alarm.timer) alarm.last = (new Date()).getDate();
if (alarm.ot!==undefined) {
@ -51,24 +56,35 @@ function showAlarm(alarm) {
require("sched").setAlarms(alarms);
load();
});
function buzz() {
require("buzz").pattern(alarm.vibrate===undefined?"..":alarm.vibrate).then(function() {
if (buzzCount--)
setTimeout(buzz, 3000);
else if(alarm.as) { // auto-snooze
buzzCount = 10;
setTimeout(buzz, 600000);
if (settings.unlockAtBuzz) {
Bangle.setLocked(false);
}
require("buzz").pattern(alarm.vibrate === undefined ? ".." : alarm.vibrate).then(() => {
if (buzzCount--) {
setTimeout(buzz, settings.buzzIntervalMillis);
} else if (alarm.as) { // auto-snooze
buzzCount = settings.buzzCount;
setTimeout(buzz, settings.defaultSnoozeMillis);
}
});
}
if ((require('Storage').readJSON('setting.json',1)||{}).quiet>1) return;
if ((require("Storage").readJSON("setting.json", 1) || {}).quiet > 1)
return;
buzz();
}
// Check for alarms
var alarms = require("sched").getAlarms();
var active = require("sched").getActiveAlarms(alarms);
if (active.length) // if there's an alarm, show it
let alarms = require("sched").getAlarms();
let active = require("sched").getActiveAlarms(alarms);
if (active.length) {
// if there's an alarm, show it
showAlarm(active[0]);
else // otherwise just go back to default app
} else {
// otherwise just go back to default app
setTimeout(load, 100);
}

72
apps/sched/settings.js Normal file
View File

@ -0,0 +1,72 @@
(function (back) {
let settings = require("sched").getSettings();
E.showMenu({
"": { "title": /*LANG*/"Scheduler" },
/*LANG*/"< Back": () => back(),
/*LANG*/"Unlock at Buzz": {
value: settings.unlockAtBuzz,
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
onchange: v => {
settings.unlockAtBuzz = v;
require("sched").setSettings(settings);
}
},
/*LANG*/"Default Auto Snooze": {
value: settings.defaultAutoSnooze,
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
onchange: v => {
settings.defaultAutoSnooze = v;
require("sched").setSettings(settings);
}
},
/*LANG*/"Default Snooze": {
value: settings.defaultSnoozeMillis / 60000,
min: 5,
max: 30,
step: 5,
format: v => v + /*LANG*/" min",
onchange: v => {
settings.defaultSnoozeMillis = v * 60000;
require("sched").setSettings(settings);
}
},
/*LANG*/"Buzz Count": {
value: settings.buzzCount,
min: 5,
max: 15,
step: 1,
onchange: v => {
settings.buzzCount = v;
require("sched").setSettings(settings);
}
},
/*LANG*/"Buzz Interval": {
value: settings.buzzIntervalMillis / 1000,
min: 1,
max: 5,
step: 1,
format: v => v + /*LANG*/"s",
onchange: v => {
settings.buzzIntervalMillis = v * 1000;
require("sched").setSettings(settings);
}
},
/*LANG*/"Default Alarm Pattern": require("buzz_menu").pattern(settings.defaultAlarmPattern, v => {
settings.defaultAlarmPattern = v;
require("sched").setSettings(settings);
}),
/*LANG*/"Default Timer Pattern": require("buzz_menu").pattern(settings.defaultTimerPattern, v => {
settings.defaultTimerPattern = v;
require("sched").setSettings(settings);
})
});
});