diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js new file mode 100644 index 000000000..d7375f79a --- /dev/null +++ b/apps/sleeplogalarm/lib.js @@ -0,0 +1,133 @@ +// load library +var sched = require("sched"); + +// find next active alarm in range +function getNextAlarm(allAlarms, from, to, withId) { + if (withId) allAlarms = allAlarms.map((a, idx) => { + a.idx = idx; + return a; + }); + // return next + return sched.getActiveAlarms( + // filter for active alarms in range + allAlarms.filter(a => a.on && !a.timer && a.t >= from && a.t < to) + ).map(a => { + // add time to alarm + a.tTo = sched.getTimeToAlarm(a); + return a; + // sort to get next alarm first + }).sort((a, b) => a.tTo - b.tTo)[0] || {}; +} + +// calculate a time from its date +function dateToTime(date) { + return ((date.getHours() * 60 + date.getMinutes()) * 60 + date.getSeconds()) * 1000; +} + +exports = { + // function to read settings with defaults + getSettings: function() { + return Object.assign({ + enabled: true, + hide: false, + drawTime: true, + color: g.theme.dark ? 65504 : 31, // yellow or blue + from: 4, // 0400 + to: 8, // 0800 + earlier: 30, + msgAsPrefix: true, + disableOnAlarm: false, // !!! not available if alarm is at the next day + msg: "...\n", + vibrate: "..", + as: true + }, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); + }, + + // widget reload function + widReload: function() { + // abort if onChange is not available + if (typeof (global.sleeplog || {}).onChange !== "object") return; + + // read settings to calculate alarm range + var settings = this.getSettings(); + + // set the alarm time + this.time = getNextAlarm(sched.getAlarms(), settings.from * 36E5, settings.to * 36E5).t; + + // abort if no alarm time could be found inside range + if (!this.time) return; + + // set widget width if not hidden + if (!this.hidden) this.width = 8; + + // insert sleeplogalarm function to onChange + sleeplog.onChange.sleeplogalarm = function (data) { + // abort if not changed from deep sleep to light sleep or awake + if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; + + // get settings from widget, now and calculate time of now + var settings = WIDGETS.sleeplogalarm; + var now = new Date(); + var tNow = dateToTime(now); + + // execute trigger function if inside the alarm range + if (tNow >= settings.time - settings.earlier * 6E4 && + tNow < settings.time) require("sleeplogalarm").trigger(now, tNow); + }; + }, + + // trigger function + trigger: function(now, tNow) { + // define settings + var settings = this.getSettings(); + + // calculate then date + var then = new Date(now + settings.earlier * 6E4); + + // read all alarms + var allAlarms = sched.getAlarms(); + + // find first active alarm + var alarm = firstActiveAlarm(allAlarms); + + // return if no alarm is found + if (!alarm) return; + + // disable early triggered alarm if set and now and then on the same day + if (settings.disableOnAlarm && now.getDate() === then.getDate()) { + // add indexes to find alarm to temporary disable + allAlarms = allAlarms.map((a, idx) => { + a.idx = idx; + return a; + }); + // get index of first active alarm + var idx = firstActiveAlarm(allAlarms).idx; + // set this alarms last to then + allAlarms[idx].last = then.getDate(); + // remove added indexes + allAlarms = allAlarms.map(a => { + delete a.idx; + return a; + }); + } + + // add new alarm for now with data from found alarm + allAlarms.push({ + id: "sleeplog", + appid: "sleeplog", + on: true, + t: (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000), + dow: 127, + msg: settings.msg + (settings.msgAsPrefix ? alarm.msg || "" : ""), + vibrate: settings.vibrate || alarm.vibrate, + as: settings.as, + del: true + }); + + // write changes + sched.setAlarms(allAlarms); + + // trigger sched.js + load("sched.js"); + } +}; \ No newline at end of file diff --git a/apps/sleeplogalarm/metadata.json b/apps/sleeplogalarm/metadata.json index 198d8e07a..fc1d546da 100644 --- a/apps/sleeplogalarm/metadata.json +++ b/apps/sleeplogalarm/metadata.json @@ -11,8 +11,8 @@ "dependencies": {"sleeplog": "app"}, "readme": "README.md", "storage": [ + {"name": "sleeplogalarm", "url": "lib.js"}, {"name": "sleeplogalarm.settings.js", "url": "settings.js"}, - {"name": "sleeplogalarm.trigger.js", "url": "trigger.js"}, {"name": "sleeplogalarm.wid.js", "url": "widget.js"} ] } diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js index 8719761dd..f6787f3bd 100644 --- a/apps/sleeplogalarm/settings.js +++ b/apps/sleeplogalarm/settings.js @@ -148,6 +148,13 @@ writeSetting(); } ), + /*LANG*/"auto snooze": { + value: settings.as, + onchange: v => { + settings.as = v; + writeSetting(); + } + }, /*LANG*/"Widget": () => showWidMenu(), /*LANG*/"Enabled": { value: settings.enabled, diff --git a/apps/sleeplogalarm/trigger.js b/apps/sleeplogalarm/trigger.js deleted file mode 100644 index cc4dd6f12..000000000 --- a/apps/sleeplogalarm/trigger.js +++ /dev/null @@ -1,75 +0,0 @@ -exports = function(now, tNow) { - // define settings - var settings = Object.assign({ - from: 4, // 0400 - to: 8, // 0800 - earlier: 30, - msgAsPrefix: true, - disableOnAlarm: false, // !!! not available if alarm is at the next day - msg: "...\n", - vibrate: "..", - as: true - }, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); - - // calculate then date - var then = new Date(now + settings.earlier * 6E4); - - // load library - var sched = require("sched"); - - // define function to return first active alarm in range to come - function firstActiveAlarm(allAlarms) { - return (sched.getActiveAlarms(allAlarms.filter( - // filter for active alarms, ... - a => a.on && !a.timer && - // after now+10s and in alarm range - a.t > tNow && a.t >= settings.from * 36E5 && a.t < settings.to * 36E5 - ), then) || []).sort((a, b) => a.t > b.t)[0]; - } - - // read all alarms - var allAlarms = sched.getAlarms(); - - // find first active alarm - var alarm = firstActiveAlarm(allAlarms); - - // return if no alarm is found - if (!alarm) return; - - // disable early triggered alarm if set and now and then on the same day - if (settings.disableOnAlarm && now.getDate() === then.getDate()) { - // add indexes to find alarm to temporary disable - allAlarms = allAlarms.map((a, idx) => { - a.idx = idx; - return a; - }); - // get index of first active alarm - var idx = firstActiveAlarm(allAlarms).idx; - // set this alarms last to then - allAlarms[idx].last = then.getDate(); - // remove added indexes - allAlarms = allAlarms.map(a => { - delete a.idx; - return a; - }); - } - - // add new alarm for now with data from found alarm - allAlarms.push({ - id: "sleeplog", - appid: "sleeplog", - on: true, - t: (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000), - dow: 127, - msg: settings.msg + (settings.msgAsPrefix ? alarm.msg || "" : ""), - vibrate: settings.vibrate || alarm.vibrate, - as: settings.as, - del: true - }); - - // write changes - sched.setAlarms(allAlarms); - - // trigger sched.js - load("sched.js"); -}; \ No newline at end of file diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index 5ccc57cda..d0e60b488 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -1,64 +1,26 @@ -// read settings to calculate alarm range -settings = Object.assign({ // if using var here settings will always be undefined - enabled: true, - hide: false, - drawRange: true, - color: g.theme.dark ? 65504 : 31, // yellow or blue - from: 4, // 0400 - to: 8, // 0800 - earlier: 30 -}, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); - // check if enabled in settings -if (settings.enabled) { +if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enabled: true}).enabled) { // insert neccessary settings into widget WIDGETS.sleeplogalarm = { area: "tl", width: 0, - drawRange: settings.drawRange, + drawTime: settings.drawTime, color: settings.color, - from: settings.from, - to: settings.to, + time: 0, earlier: settings.earlier, draw: function () { // draw zzz g.reset().setColor(this.color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); - // draw alarm range times if enabled - if (this.drawRange) { + // draw time of alarm if enabled + if (this.drawTime && this.time) { // directly include Font4x5Numeric - g.setFontCustom(atob("CAZMA/H4PgvXoK1+DhPg7W4P1uCEPg/X4O1+AA=="), 46, atob("AgQEAgQEBAQEBAQE"), 5); - g.drawString(this.from, this.x + 1, this.y + 12); - g.setFontAlign(1, 1).drawString(this.to, this.x + this.width + 1, this.y + 23); + g.setFontCustom(atob("CAZMA/H4PgvXoK1+DhPg7W4P1uCEPg/X4O1+AA=="), 46, atob("AgQEAgQEBAQEBAQE"), 5).setFontAlign(1, 1); + g.drawString(0|(this.time / 36E5), this.x + this.width + 1, this.y + 12); + g.drawString(0|((this.time / 36E5)%1 * 60), this.x + this.width + 1, this.y + 23); } }, - reload: function () { - // abort if onChange is not available - if (typeof (global.sleeplog || {}).onChange !== "object") return; - - // abort if no alarm exists inside range - if (!(require("Storage").readJSON("sched.json", 1) || []) - .filter(a => a.on && !a.timer) - .some(a => a.t >= this.from * 36E5 && a.t < this.to * 36E5)) return; - - // set widget width if not hidden - if (!this.hidden) this.width = 8; - - // insert sleeplogalarm function to onChange - sleeplog.onChange.sleeplogalarm = function (data) { - // abort if not changed from deep sleep to light sleep or awake - if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; - - // get cahed data, now and calculate time of now - var settings = WIDGETS.sleeplogalarm; - var now = new Date(); - var tNow = (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000); - - // execute trigger function if now is inside the alarm range - if (tNow + settings.earlier * 6E4 >= settings.from * 36E5 && - tNow < settings.to * 36E5) require("sleeplogalarm.trigger.js")(now, tNow); - }; - } + reload: require("sleeplogalarm").widReload() }; // load widget