diff --git a/apps/run/app.js b/apps/run/app.js index 31fd3336c..f689daebe 100644 --- a/apps/run/app.js +++ b/apps/run/app.js @@ -7,8 +7,6 @@ var fontValue = B2 ? "6x15:2" : "6x8:3"; var headingCol = "#888"; var fixCount = 0; var isMenuDisplayed = false; -var nextNotifyTime = 0; -var nextNotifyDist = 0; g.clear(); Bangle.loadWidgets(); @@ -24,9 +22,20 @@ let settings = Object.assign({ B5: "step", B6: "caden", paceLength: 1000, - notifyDist: 0, - notifyTime: 0, - notifySteps: 0, + notify: { + dist: { + value: 0, + notification: [], + }, + steps: { + value: 0, + notification: [], + }, + time: { + value: 0, + notification: [], + }, + }, }, require("Storage").readJSON("run.json", 1) || {}); var statIDs = [settings.B1,settings.B2,settings.B3,settings.B4,settings.B5,settings.B6].filter(s=>s!==""); var exs = ExStats.getStats(statIDs, settings); @@ -76,11 +85,11 @@ for (var i=0;ilayout[e.id].label = e.getString()); if (sb) sb.on('changed', e=>layout[e.id].label = e.getString()); if (sa) sa.on('notify', (e)=>{ - Bangle.buzz(); + settings.notify[id].notifications.forEach((vibTime) => Bangle.buzz(vibTime)); console.log(`notify from ${JSON.stringify(e)}`); }); if (sb) sa.on('notify', (e)=>{ - Bangle.buzz(); + settings.notify[id].notifications.forEach((vibTime) => Bangle.buzz(vibTime)); console.log(`notify from ${JSON.stringify(e)}`); }); } diff --git a/apps/run/settings.js b/apps/run/settings.js index 9a8259f85..8606ef304 100644 --- a/apps/run/settings.js +++ b/apps/run/settings.js @@ -17,9 +17,20 @@ B5: "step", B6: "caden", paceLength: 1000, // TODO: Default to either 1km or 1mi based on locale - notifyDist: 0, - notifyTime: 0, - notifySteps: 0, + notify: { + dist: { + increment: 0, + notification: [], + }, + steps: { + increment: 0, + notification: [], + }, + time: { + increment: 0, + notification: [], + }, + }, }, storage.readJSON(SETTINGS_FILE, 1) || {}); function saveSettings() { storage.write(SETTINGS_FILE, settings) @@ -50,6 +61,35 @@ saveSettings(); } }; + var vibPatterns = [/*LANG*/"Off", ".", "-", "--", "-.-", "---"]; + var vibTimes = [[], [100], [500],[500,500],[500,100,500],[500,500,500]]; + menu[/*LANG*/"Time Notifctn"] = { + value: Math.max(0,vibPatterns.indexOf(settings.timeNotification)), + min: 0, max: vibPatterns.length, + format: v => vibPatterns[v]||"Off", + onchange: v => { + settings.notify.time.notification = vibTimes[v]; + saveSettings(); + } + } + menu[/*LANG*/"Dist Notifctn"] = { + value: Math.max(0,vibPatterns.indexOf(settings.distNotification)), + min: 0, max: vibPatterns.length, + format: v => vibPatterns[v]||"Off", + onchange: v => { + settings.notify.dist.notification = vibTimes[v]; + saveSettings(); + } + } + menu[/*LANG*/"Step Notifctn"] = { + value: Math.max(0,vibPatterns.indexOf(settings.stepNotification)), + min: 0, max: vibPatterns.length, + format: v => vibPatterns[v]||"Off", + onchange: v => { + settings.notify.steps.notification = vibTimes[v]; + saveSettings(); + } + } ExStats.appendMenuItems(menu, settings, saveSettings); Object.assign(menu,{ 'Box 1': getBoxChooser("B1"), diff --git a/modules/exstats.js b/modules/exstats.js index 7055b5b35..c9fa54224 100644 --- a/modules/exstats.js +++ b/modules/exstats.js @@ -63,9 +63,24 @@ var state = { // cadence // steps per minute adjusted if <1 minute // BPM // beats per minute // BPMage // how many seconds was BPM set? - // Notifies: 0 for disabled, otherwise how often to notify in meters and seconds - notifyDist: 0, notifyTime: 0, notifySteps: 0, - nextNotifyDist: 0, nextNotifyTime: 0, nextNotifySteps: 0, + // Notifies: 0 for disabled, otherwise how often to notify in meters, seconds, or steps + notify: { + dist: { + increment: 0, + notification: [], + next: 0, + }, + steps: { + increment: 0, + notification: [], + next: 0, + }, + time: { + increment: 0, + notification: [], + next: 0, + }, + }, }; // list of active stats (indexed by ID) var stats = {}; @@ -118,9 +133,9 @@ Bangle.on("GPS", function(fix) { if (stats["pacea"]) stats["pacea"].emit("changed",stats["pacea"]); if (stats["pacec"]) stats["pacec"].emit("changed",stats["pacec"]); if (stats["speed"]) stats["speed"].emit("changed",stats["speed"]); - if (state.notifyDist > 0 && state.nextNotifyDist < stats["dist"]) { + if (state.notify.dist.increment > 0 && state.notify.dist.next < stats["dist"]) { stats["dist"].emit("notify",stats["dist"]); - state.nextNotifyDist = stats["dist"] + state.notifyDist; + state.notify.dist.next = stats["dist"] + state.notify.dist.increment; } }); @@ -129,9 +144,9 @@ Bangle.on("step", function(steps) { if (stats["step"]) stats["step"].emit("changed",stats["step"]); state.stepHistory[0] += steps-state.lastStepCount; state.lastStepCount = steps; - if (state.notifySteps > 0 && state.nextNotifySteps < steps) { - stats["step"].emit("notify",stats["step"]); - state.nextNotifySteps = steps + state.notifySteps; + if (state.notify.steps.increment > 0 && state.notify.steps.next < steps) { + stats["steps"].emit("notify",stats["steps"]); + state.notify.steps.next = steps + state.notify.steps.increment; } }); Bangle.on("HRM", function(h) { @@ -158,17 +173,25 @@ exports.getList = function() { /** Instantiate the given list of statistic IDs (see comments at top) options = { paceLength : meters to measure pace over - notifyDist : meters to notify have elapsed (repeats) - notifyTime : ms to notify have elapsed (repeats) - notifySteps : number of steps to notify have elapsed (repeats) + notify: { + dist: { + increment: 0 to not notify on distance milestones, otherwise the number of meters to notify after, repeating + }, + steps: { + increment: 0 to not notify on step milestones, otherwise the number of steps to notify after, repeating + }, + time: { + increment: 0 to not notify on time milestones, otherwise the number of milliseconds to notify after, repeating + } + } } */ exports.getStats = function(statIDs, options) { options = options||{}; options.paceLength = options.paceLength||1000; - options.notifyDist = options.notifyDist||0; - options.notifyTime = options.notifyTime||0; - options.notifySteps = options.notifySteps||0; + options.notify.dist.increment = options.notify.dist.increment||0; + options.notify.steps.increment = options.notify.steps.increment||0; + options.notify.time.increment = options.notify.time.increment||0; var needGPS,needHRM; // ====================== if (statIDs.includes("time")) { @@ -254,9 +277,9 @@ exports.getStats = function(statIDs, options) { state.BPM = 0; if (stats["bpm"]) stats["bpm"].emit("changed",stats["bpm"]); } - if (state.notifyTime > 0 && state.nextNotifyTime < now) { + if (state.notify.time.increment > 0 && state.notify.time.next < now) { stats["time"].emit("notify",stats["time"]); - state.nextNotifyTime = stats["time"] + state.notifyTime; + state.notify.time.next = stats["time"] + state.notify.time.increment; } }, 1000); function reset() { @@ -270,19 +293,17 @@ exports.getStats = function(statIDs, options) { state.curSpeed = 0; state.BPM = 0; state.BPMage = 0; - state.notifyTime = options.notifyTime; - state.notifyDist = options.notifyDist; - state.notifySteps = options.notifySteps; + state.notify = options.notify; console.log("options:"); console.log(JSON.stringify(options)); - if (options.notifyTime) { - state.nextNotifyTime = state.startTime + options.notifyTime; + if (options.notify.dist.increment > 0) { + state.notify.dist.next = state.distance + options.notify.dist.increment; } - if (options.notifyDist) { - state.nextNotifyDist = state.distance + options.notifyDist; + if (options.notify.steps.increment > 0) { + state.notify.steps.next = state.startTime + options.notify.steps.increment; } - if (options.notifySteps) { - state.nextNotifySteps = state.startSteps + options.notifySteps; + if (options.notify.time.increment > 0) { + state.notify.time.next = state.startTime + options.notify.time.increment; } console.log("state:"); console.log(JSON.stringify(state)); @@ -316,10 +337,10 @@ exports.appendMenuItems = function(menu, settings, saveSettings) { var distAmts = [0, 1000,1609,21098,42195]; menu['Ntfy Dist'] = { min: 0, max: distNames.length-1, - value: Math.max(distAmts.indexOf(settings.notifyDist),0), + value: Math.max(distAmts.indexOf(settings.notify.dist.increment),0), format: v => distNames[v], onchange: v => { - settings.notifyDist = distAmts[v]; + settings.notify.dist.increment = distAmts[v]; saveSettings(); }, }; @@ -327,10 +348,10 @@ exports.appendMenuItems = function(menu, settings, saveSettings) { var timeAmts = [0, 30000, 60000, 120000, 300000, 600000, 1800000, 3600000]; menu['Ntfy Time'] = { min: 0, max: timeNames.length-1, - value: Math.max(timeAmts.indexOf(settings.notifyTime),0), + value: Math.max(timeAmts.indexOf(settings.notify.time.increment),0), format: v => timeNames[v], onchange: v => { - settings.notifyTime = timeAmts[v]; + settings.notify.time.increment = timeAmts[v]; saveSettings(); }, }; @@ -338,10 +359,10 @@ exports.appendMenuItems = function(menu, settings, saveSettings) { var stepAmts = [0, 100, 500, 1000, 5000, 10000]; menu['Ntfy Steps'] = { min: 0, max: stepNames.length-1, - value: Math.max(stepAmts.indexOf(settings.notifySteps),0), + value: Math.max(stepAmts.indexOf(settings.notify.steps.increment),0), format: v => stepNames[v], onchange: v => { - settings.notifySteps = stepAmts[v]; + settings.notify.steps.increment = stepAmts[v]; saveSettings(); }, };