From da82682f6b6600f58468944bbe61a36a3739020a Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Thu, 25 Mar 2021 23:25:04 +0100 Subject: [PATCH] add qmsched: Quiet Mode schedule --- apps.json | 20 ++++- apps/qmsched/ChangeLog | 1 + apps/qmsched/README.md | 5 ++ apps/qmsched/app.js | 133 +++++++++++++++++++++++++++++++ apps/qmsched/app.png | Bin 0 -> 1400 bytes apps/qmsched/boot.js | 24 ++++++ apps/qmsched/icon.js | 2 + apps/qmsched/lib.js | 17 ++++ apps/qmsched/screenshot_edit.png | Bin 0 -> 3644 bytes apps/qmsched/screenshot_main.png | Bin 0 -> 3661 bytes 10 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 apps/qmsched/ChangeLog create mode 100644 apps/qmsched/README.md create mode 100644 apps/qmsched/app.js create mode 100644 apps/qmsched/app.png create mode 100644 apps/qmsched/boot.js create mode 100644 apps/qmsched/icon.js create mode 100644 apps/qmsched/lib.js create mode 100644 apps/qmsched/screenshot_edit.png create mode 100644 apps/qmsched/screenshot_main.png diff --git a/apps.json b/apps.json index b0c91f619..8f0ace1d3 100644 --- a/apps.json +++ b/apps.json @@ -3059,5 +3059,23 @@ {"name":"waypoints.json","url":"waypoints.json","evaluate":false}, {"name":"kitchen.img","url":"kitchen.icon.js","evaluate":true} ] -} +}, + { "id": "qmsched", + "name": "Quiet Mode Schedule", + "shortName":"Quiet Mode", + "icon": "app.png", + "version":"0.01", + "description": "Automatically turn Quiet Mode on or off at set times", + "readme": "README.md", + "tags": "tool", + "storage": [ + {"name":"qmsched","url":"lib.js"}, + {"name":"qmsched.app.js","url":"app.js"}, + {"name":"qmsched.boot.js","url":"boot.js"}, + {"name":"qmsched.img","url":"icon.js","evaluate":true} + ], + "data": [ + {"name":"qmsched.json"} + ] + } ] diff --git a/apps/qmsched/ChangeLog b/apps/qmsched/ChangeLog new file mode 100644 index 000000000..7f837e50e --- /dev/null +++ b/apps/qmsched/ChangeLog @@ -0,0 +1 @@ +0.01: First version diff --git a/apps/qmsched/README.md b/apps/qmsched/README.md new file mode 100644 index 000000000..1ccddbf8c --- /dev/null +++ b/apps/qmsched/README.md @@ -0,0 +1,5 @@ +# Quiet Mode Schedule + +Automatically turn Quiet Mode on or off at set times. + +![Main menu](screenshot_main.png) ![Edit Schedule menu](screenshot_edit.png) diff --git a/apps/qmsched/app.js b/apps/qmsched/app.js new file mode 100644 index 000000000..7761be31c --- /dev/null +++ b/apps/qmsched/app.js @@ -0,0 +1,133 @@ +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +const modeNames = ["Off", "Alarms", "Silent"]; +let scheds = require("Storage").readJSON("qmsched.json", 1); +/*scheds = [ + { hr : 6.5, // hours + minutes/60 + last : 0, // last day of the month we fired on - so we don't switch twice in one day! + mode : 1, // quiet mode (0/1/2) + } +];*/ +if (!scheds) { + // set default schedule on first load of app + scheds = [ + {"hr": 8, "mode": 0, "last": 25}, + {"hr": 22, "mode": 1, "last": 25}, + ]; + require("Storage").writeJSON("qmsched.json", scheds); +} + +function formatTime(t) { + const hrs = 0|t; + const mins = Math.round((t-hrs)*60); + return (" "+hrs).substr(-2)+":"+("0"+mins).substr(-2); +} + +function getCurrentHr() { + const time = new Date(); + return time.getHours()+(time.getMinutes()/60)+(time.getSeconds()/3600); +} + +function showMainMenu() { + const menu = { + "": {"title": "Quiet Mode"}, + "Current Mode": { + value: (require("Storage").readJSON("setting.json", 1) || {}).quiet|0, + format: v => modeNames[v], + onchange: function(v) { + if (v<0) v = 2; + if (v>2) v = 0; + require("qmsched").setMode(v); + this.value = v; + }, + }, + }; + scheds.sort((a, b) => (a.hr-b.hr)); + scheds.forEach((sched, idx) => { + const name = modeNames[sched.mode]; + const txt = formatTime(sched.hr)+" ".repeat(14-name.length)+name; + menu[txt] = function() { + showEditMenu(idx); + }; + }); + menu["Add Schedule"] = () => showEditMenu(-1); + menu["< Back"] = () => {load();}; + return E.showMenu(menu); +} + +function showEditMenu(index) { + const isNew = index<0; + let hrs = 12, mins = 0; + let mode = 1; + if (!isNew) { + const s = scheds[index]; + hrs = 0|s.hr; + mins = Math.round((s.hr-hrs)*60); + mode = s.mode; + } + const menu = { + "": {"title": (isNew ? "Add" : "Edit")+" Schedule"}, + "Hours": { + value: hrs, + onchange: function(v) { + if (v<0) v = 23; + if (v>23) v = 0; + hrs = v; + this.value = v; + }, // no arrow fn -> preserve 'this' + }, + "Minutes": { + value: mins, + onchange: function(v) { + if (v<0) v = 59; + if (v>59) v = 0; + mins = v; + this.value = v; + }, // no arrow fn -> preserve 'this' + }, + "Switch to": { + value: mode, + format: v => modeNames[v], + onchange: function(v) { + if (v<0) v = 2; + if (v>2) v = 0; + mode = v; + this.value = v; + }, // no arrow fn -> preserve 'this' + }, + }; + function getSched() { + const hr = hrs+(mins/60); + let day = 0; + // If schedule is for tomorrow not today (eg, in the past), set day + if (hr Save"] = function() { + if (isNew) { + scheds.push(getSched()); + } else { + scheds[index] = getSched(); + } + require("Storage").writeJSON("qmsched.json", scheds); + showMainMenu(); + }; + if (!isNew) { + menu["> Delete"] = function() { + scheds.splice(index, 1); + require("Storage").writeJSON("qmsched.json", scheds); + showMainMenu(); + }; + } + menu["< Cancel"] = showMainMenu; + return E.showMenu(menu); +} + +showMainMenu(); diff --git a/apps/qmsched/app.png b/apps/qmsched/app.png new file mode 100644 index 0000000000000000000000000000000000000000..cf1fc29bcfb25b0d18a16615e05b939adb03a9e3 GIT binary patch literal 1400 zcmV-;1&8{HP)N8&e6eu>x{m_s- z(B9lo9~VO9LpKnHj{<)X{6R2$6b^^kc#=dXDpuC6N7zSfIf-s=Z))5dFGi1(gXMn_ zm1luRV^05w=zffzw`DQ6)3JTFg%4ta7MqquD}BB$k~ zZGkPoSEM!%kdJV%FD7jz%|JxSGI8?d=BpUmM4XnKLSZafEz7!FT*eJj(hNkDEE5eK z(>}(%d4LQI-J`$Y_Ym7JM*xr*;`Jk?lbg;?@p}E4{NrEmH5gm~Kzs;Gg`J1W@C>2y zjJH5rt^nXZKnRby4;qkb02qMq8QMRV288GO1BYEGk-m9%hSoLA$Fv5PF+|x>-9gpE ze>pd?H00Tbrwl~2eBM=d)&9gVWx|uv0)UZ+NE-k~7Q!=twq_Mae@_QOk7X5k^^ryf ztc|fFo*{hJ2CptW?S4I;Jr&bD2js*%fArVMxa>|{i0>g;a@Tq5imdB4K#!4uY3?I| zdGM5pv1qtnPm}4^kNXlb0x9r1 zF#mN80Sqdq2n4n76>{0jnE(Pe#cIf@E^^+*Ilg6k%FXrwn1o<{4B~jKPn-M}N3M-TN0Y%>hWmfF0{^ zQZ?sH-wgoZXIUC5OLU3kC8SvW9yJWzo%TTsNC5nKkeLsGN%p629AsqE|BNr0L$jt9 zgm1CD^agBH>OP@A6P5)#_m6|>@zLEWOcEu}zzHVM>wgR6xs| zr;5S1{y7+w0mUH2DAN$lMP-6zQlv=05JmbbNlm-k2pTecTtf63D%TM%gI)qIZuzKk z%9+dK-@wJYSWf_{bZl$3WorC&eS$7~^KQc59xpGHhvkVZT4JDv0TP8EVs{uZV*Bb~ zd3m)z>;MJ1da!V!GCfb3k#8T<^OVAg%CublGF7}=h~dwGSlfVWaZX(q!`kL#jrQh- zdQmnp6yk&Or`FAko;&OSCEG*4TgrUk3y?1Rpk55CV%E0Md8g}~Y;O2GCKHOV^;FA& z&ggl=zKMrheH;5zgstsO4eyM!A5VIGWp#1tS)&@2C;bOIms?B5>cnIK0000ig literal 0 HcmV?d00001 diff --git a/apps/qmsched/boot.js b/apps/qmsched/boot.js new file mode 100644 index 000000000..3c53ef3f7 --- /dev/null +++ b/apps/qmsched/boot.js @@ -0,0 +1,24 @@ +// apply Quiet Mode schedules +(function qm() { + let scheds = require("Storage").readJSON("qmsched.json", 1) || []; + if (!scheds.length) return; + let next,idx; + scheds.forEach(function(s, i) { + if (!next || (s.hr+s.last*24)<(next.hr+next.last*24)) { + next = s; + idx = i; + } + }); + const now = new Date(), + hr = now.getHours()+(now.getMinutes()/60)+(now.getSeconds()/3600); + let t = 3600000*(next.hr-hr); + if (next.last===now.getDate()) t += 86400000; + /* update quiet mode at the correct time. */ + setTimeout(function() { + let scheds = require("Storage").readJSON("qmsched.json", 1) || []; + require("qmsched").setMode(scheds[idx].mode); + scheds[idx].last = (new Date()).getDate(); + require("Storage").writeJSON("qmsched.json", scheds); + qm(); // schedule next update + }, t); +})(); diff --git a/apps/qmsched/icon.js b/apps/qmsched/icon.js new file mode 100644 index 000000000..c0f4e2b66 --- /dev/null +++ b/apps/qmsched/icon.js @@ -0,0 +1,2 @@ +// https://icons8.com/icon/19324/no-reminders +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AElksF1wwtF4YwO0WiGFguBGFovfGB3MAAgwnFooxfGBAuJGEguLGEV/F5owh0YvpGH4vhGCQvd0YwQF7vMGCAveGCAvfGB4vgGBwvhGBouhGFLkIGEouIGEwvKGBguiGEQuNGEHN5owa5ouQ53P5/O5wyOGA3NDAIbBLyAUCAAQzCNBQwF0gVDXiQoBGQgAEEIILE0iSJdiozCFQw1FGBJgSABSVIeg7wQGSDDMFyQ0VCQQwdAAWcAAwPHGD4vPGD+iAAwRJGEgRLGEQRNeTwARF1wA/AH4AX")) \ No newline at end of file diff --git a/apps/qmsched/lib.js b/apps/qmsched/lib.js new file mode 100644 index 000000000..6cdf4f181 --- /dev/null +++ b/apps/qmsched/lib.js @@ -0,0 +1,17 @@ +/** + * Set new Quiet Mode and apply Bangle options + * @param {int} mode Quiet Mode + */ +exports.setMode = function(mode) { + let s = require("Storage").readJSON("setting.json", 1) || {}; + s.quiet = mode; + require("Storage").writeJSON("setting.json", s); + if (s.options) Bangle.setOptions(s.options); + if (mode && s.qmOptions) Bangle.setOptions(s.qmOptions); + if (mode && s.qmBrightness) { + if (s.qmBrightness!=1) Bangle.setLCDBrightness(s.qmBrightness); + } else { + if (s.brightness && s.brightness!=1) Bangle.setLCDBrightness(s.brightness); + } + if (mode && s.qmTimeout) Bangle.setLCDTimeout(s.qmTimeout); +}; \ No newline at end of file diff --git a/apps/qmsched/screenshot_edit.png b/apps/qmsched/screenshot_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..88b7fcad4ac9df533f69b14675f1dcf3d9c25b1e GIT binary patch literal 3644 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 literal 0 HcmV?d00001