|
| 1 | +const SETTINGS_FILE = "schedclock.settings.json"; |
| 2 | +const APP_ID = "schedclock"; |
| 3 | + |
| 4 | +/** |
| 5 | + * Called directly by an alarm to load a specific clock face |
| 6 | + * @param {string} faceSrc - Source file of the clock face to load (e.g. "myclock.js") |
| 7 | + **/ |
| 8 | +const setClock = function(faceSrc) { |
| 9 | + const settings = require("Storage").readJSON("setting.json", 1) || {}; |
| 10 | + // Only change the clock if it's different |
| 11 | + if (faceSrc && settings.clock !== faceSrc) { |
| 12 | + const face = require("Storage").read(faceSrc); |
| 13 | + // If the face doesn't exist, do nothing (but log it) |
| 14 | + if (!face) { |
| 15 | + console.log("schedclock: Invalid clock face", faceSrc); |
| 16 | + return; |
| 17 | + } |
| 18 | + settings.clock = faceSrc; |
| 19 | + settings.clockHasWidgets = face.includes("Bangle.loadWidgets"); |
| 20 | + require("Storage").writeJSON("setting.json", settings); |
| 21 | + if(Bangle.CLOCK) load(); // Reload clock if we're on it |
| 22 | + } |
| 23 | +}; |
| 24 | + |
| 25 | +/** |
| 26 | + * Handle alarms and resetting them |
| 27 | + * @param {number} index Index of the alarm that went off |
| 28 | + * @param {string} clock Clockface |
| 29 | + */ |
| 30 | +exports.onAlarm = function(index, clock) { |
| 31 | + const date = new Date(); |
| 32 | + const Sched = require("sched"); |
| 33 | + const alarm = Sched.getAlarm(`${APP_ID}.${index}`); |
| 34 | + alarm.last = date.getDate(); // prevent second run on the same day |
| 35 | + Sched.setAlarm(alarm.id, alarm); |
| 36 | + setClock(clock); |
| 37 | +}; |
| 38 | + |
| 39 | +/** |
| 40 | + * Function to sync all alarms in the scheduler with the settings file. |
| 41 | + * Called every time settings are changed; maybe a bit excessive, but keeps things simple. |
| 42 | + **/ |
| 43 | +exports.syncAlarms = function() { |
| 44 | + const Sched = require("sched"); |
| 45 | + const settings = require("Storage").readJSON(SETTINGS_FILE, 1) || []; |
| 46 | + |
| 47 | + // Remove all existing alarms from the scheduler library |
| 48 | + Sched |
| 49 | + .getAlarms() |
| 50 | + .filter(a => a.appid && a.appid === APP_ID) |
| 51 | + .forEach(a => Sched.setAlarm(a.id, undefined)); |
| 52 | + |
| 53 | + // If the app is disabled, we're done. |
| 54 | + if (!settings.enabled) return; |
| 55 | + |
| 56 | + // Alarms need "last" set to let sched know they've already ran for the day |
| 57 | + // So if an alarm is for before "now", set last to yesterday so it still triggers today |
| 58 | + // else set last to today. |
| 59 | + const currentDate = new Date(); |
| 60 | + const currentTime = (currentDate.getHours()*3600000)+(currentDate.getMinutes()*60000)+(currentDate.getSeconds()*1000); |
| 61 | + const dayOfMonthToday = currentDate.getDate(); |
| 62 | + const dayOfMonthYesterday = dayOfMonthToday - 1; |
| 63 | + |
| 64 | + // Add a new alarm for each setting item |
| 65 | + settings.sched.forEach((item, index) => { |
| 66 | + |
| 67 | + // Skip invalid records |
| 68 | + if (item.hour === undefined || item.minute === undefined) return; |
| 69 | + |
| 70 | + const scheduledTime = (item.hour * 3600000) + (item.minute * 60000); |
| 71 | + |
| 72 | + // Create the new alarm object and save it using a unique ID. |
| 73 | + Sched.setAlarm(`${APP_ID}.${index}`, { |
| 74 | + t: scheduledTime, // time in milliseconds since midnight |
| 75 | + on: true, |
| 76 | + rp: true, |
| 77 | + last: (scheduledTime > currentTime) ? dayOfMonthYesterday : dayOfMonthToday, |
| 78 | + dow: item.dow, |
| 79 | + hidden: true, |
| 80 | + appid: APP_ID, |
| 81 | + js: `require('${APP_ID}.lib.js').onAlarm(${index},'${item.face}')`, |
| 82 | + }); |
| 83 | + }); |
| 84 | +}; |
0 commit comments