From 30ade21eac2e17476d05fe2c94ce49be6ea528ef Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Tue, 8 Mar 2022 20:16:00 +0100 Subject: [PATCH] New power management app for setting a charging alarm and voltage offset --- apps/powermanager/ChangeLog | 1 + apps/powermanager/README.md | 15 ++++ apps/powermanager/app.png | Bin 0 -> 1202 bytes apps/powermanager/boot.js | 29 ++++++++ apps/powermanager/default.json | 4 + apps/powermanager/metadata.json | 17 +++++ apps/powermanager/settings.js | 125 ++++++++++++++++++++++++++++++++ 7 files changed, 191 insertions(+) create mode 100644 apps/powermanager/ChangeLog create mode 100644 apps/powermanager/README.md create mode 100644 apps/powermanager/app.png create mode 100644 apps/powermanager/boot.js create mode 100644 apps/powermanager/default.json create mode 100644 apps/powermanager/metadata.json create mode 100644 apps/powermanager/settings.js diff --git a/apps/powermanager/ChangeLog b/apps/powermanager/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/powermanager/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/powermanager/README.md b/apps/powermanager/README.md new file mode 100644 index 000000000..f2cfcdf3e --- /dev/null +++ b/apps/powermanager/README.md @@ -0,0 +1,15 @@ +# Power manager + +Manages settings for charging. You can set a warning threshold to be able to disconnect the charger at a given percentage. Also allows to set the battery calibration offset. + +## Internals + +Battery calibration offset is set by writing `batFullVoltage` in setting.json + +## TODO + +* Optionally keep battery history and show as graph + +## Creator + +[halemmerich](https://github.com/halemmerich) diff --git a/apps/powermanager/app.png b/apps/powermanager/app.png new file mode 100644 index 0000000000000000000000000000000000000000..dc51aa01b227a901238a89efea92b9fea499c80a GIT binary patch literal 1202 zcmV;j1Wo&iP)r6rLSW%NLZf}TW{iIbICYNK}hu=e5Hx!##M_nv!a z><=66J$tXU|7)MU*IIiW+Jk9Wg2T@6_C$;SV{b|fzi#r9;-!T^> zQ@av>q`t*N#%=&i#ZGL)DRuf!#r8C2>LBtegkktZtnj>k#?4D(K20)v4Q>#`KF5fD z#tp~1H1_&I;8h3*p<9qTtHAg(@GmxFY#VtM#?ylQvIb<9C7Gw%!l(h9C=TUT9NvK3 zA=rXlIJphH3gaEIk_(%VU6^FwH$<^vP9pFXI-8L1OtKYRQPVdQ&tZHSg8g9>eoB*H zSVGVAq~mAohsh%C$RhWgay0wKII-_vY=N%jg6v0nryUg$&D)02$_Jwk+#x5t4fo&~ zgJ3{eoQ4nO!K5j@RxY4x3@@dhgkW{o9z(yg)th~LIdG^xv$Pzk$iqE-o#rq?Y25&_r(Lk zfQm3^t&#>DftRXCufeko7_eAxqbv9allqaFgcVA<(c10uOH$H-`2`K=#D+QsJX(;$ z41Aqr&TEAHSbUiTcj5^gP}N`5fUE3Dep8LEfzXMQiVUpwLI+|(`rR!OwJi-ynqhvO zXGNMP6}Psm z?cX-mRXAN-`?d=2Q4yDq{tTF$WNHnlZo9S1A2)fl3hFfr~sIp}w7WE;w1mD%P zT7zzCg8crX&a|SaKvrQ`C#nb;W+f$syo0C>Rg=H3D1jP`!1qbV?12V1T4Cr9Ps+(J zRqon2GwE3`B6pu?rovDUox=B5#9M2H7kVw}d#JAg%~lxd;S%{RYfMR98IHo=g5w_B zxI?)LLoJqzbf6WfcQx*o=VraOBxRN` zs%CJJ{6KfXb?L#X7ERFVZBq|fT)LLHcvM6lGgz1+Tz0cKS8!fQe8bwIx$0V@m>{nM zJzqjkmq>BC2?Mrk?+1r{aF?k2WWnu?68eUTMel}plfsM3aqJT_@U8r#-z&-+kVWP- zM1D~b9~>^zy4-yNUX`!-+c-h&|7HyskvRUAbj;3z!6R6Zes306%Wmv0sCcueIBZM* zZxp4GQR05Q057DzDI(k5i1!NWA1>m{@i;g=dst1-oi0irwFTB9ZMXd9M(>j0JiX7? zlmhztYCXbhUXUrPmm!W8Rk-nrd!`NItz|eAkIAFuTHK7!FWH?L&uU5o?A;sCkrCu}CMD_~&2coHWFPlaz QHUIzs07*qoM6N<$g5tA6ga7~l literal 0 HcmV?d00001 diff --git a/apps/powermanager/boot.js b/apps/powermanager/boot.js new file mode 100644 index 000000000..ff4ba8932 --- /dev/null +++ b/apps/powermanager/boot.js @@ -0,0 +1,29 @@ +(function() { + var settings = Object.assign( + require('Storage').readJSON("powermanager.default.json", true) || {}, + require('Storage').readJSON("powermanager.json", true) || {} + ); + + if (settings.warnEnabled){ + print("Charge warning enabled"); + var chargingInterval; + + function handleCharging(charging){ + if (charging){ + if (chargingInterval) clearInterval(chargingInterval); + chargingInterval = setInterval(()=>{ + if (E.getBattery() > settings.warn){ + Bangle.buzz(1000); + } + }, 10000); + } + if (chargingInterval && !charging){ + clearInterval(chargingInterval); + chargingInterval = undefined; + } + } + + Bangle.on("charging",handleCharging); + handleCharging(Bangle.isCharging()); + } +})(); diff --git a/apps/powermanager/default.json b/apps/powermanager/default.json new file mode 100644 index 000000000..a6d8412b2 --- /dev/null +++ b/apps/powermanager/default.json @@ -0,0 +1,4 @@ +{ + "warnEnabled": false, + "warn": 96 +} diff --git a/apps/powermanager/metadata.json b/apps/powermanager/metadata.json new file mode 100644 index 000000000..3ad31ba1e --- /dev/null +++ b/apps/powermanager/metadata.json @@ -0,0 +1,17 @@ +{ + "id": "powermanager", + "name": "Power Manager", + "shortName": "Power Manager", + "version": "0.01", + "description": "Allow configuration of warnings and thresholds for battery charging and display.", + "icon": "app.png", + "type": "bootloader", + "tags": "tool", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"powermanager.boot.js","url":"boot.js"}, + {"name":"powermanager.settings.js","url":"settings.js"}, + {"name":"powermanager.default.json","url":"default.json"} + ] +} diff --git a/apps/powermanager/settings.js b/apps/powermanager/settings.js new file mode 100644 index 000000000..c8aa057fa --- /dev/null +++ b/apps/powermanager/settings.js @@ -0,0 +1,125 @@ +(function(back) { + var systemsettings = require("Storage").readJSON("setting.json") || {}; + + function writeSettings(key, value) { + var s = require('Storage').readJSON(FILE, true) || {}; + s[key] = value; + require('Storage').writeJSON(FILE, s); + readSettings(); + } + + function readSettings() { + settings = Object.assign( + require('Storage').readJSON("powermanager.default.json", true) || {}, + require('Storage').readJSON(FILE, true) || {} + ); + } + + var FILE = "powermanager.json"; + var settings; + readSettings(); + + var mainmenu = { + '': { + 'title': 'Power Manager' + }, + '< Back': back, + 'Charge warning': function() { + E.showMenu(submenu_chargewarn); + }, + 'Calibrate': function() { + E.showMenu(submenu_calibrate); + } + }; + + + function roundToDigits(number, stepsize) { + return Math.round(number / stepsize) * stepsize; + } + + function getCurrentVoltageDirect() { + return (analogRead(D3) + analogRead(D3) + analogRead(D3) + analogRead(D3)) / 4; + } + + var stepsize = 0.0002; + var full = 0.32; + + function getInitialCalibrationOffset() { + return roundToDigits(systemsettings.batFullVoltage - full, stepsize) || 0; + } + + + var submenu_calibrate = { + '': { + title: "Calibrate" + }, + '< Back': function() { + E.showMenu(mainmenu); + }, + 'Offset': { + min: -0.05, + max: 0.05, + step: stepsize, + value: getInitialCalibrationOffset(), + format: v => roundToDigits(v, stepsize).toFixed((""+stepsize).length - 2), + onchange: v => { + print(typeof v); + systemsettings.batFullVoltage = v + full; + require("Storage").writeJSON("setting.json", systemsettings); + } + }, + 'Auto': function() { + var newVoltage = getCurrentVoltageDirect(); + E.showAlert("Please charge fully before auto setting").then(() => { + E.showPrompt("Set current charge as full").then((r) => { + if (r) { + systemsettings.batFullVoltage = newVoltage; + require("Storage").writeJSON("setting.json", systemsettings); + //reset value shown in menu to the newly set one + submenu_calibrate.Offset.value = getInitialCalibrationOffset(); + E.showMenu(mainmenu); + } + }); + }); + }, + 'Clear': function() { + E.showPrompt("Clear charging offset?").then((r) => { + if (r) { + delete systemsettings.batFullVoltage; + require("Storage").writeJSON("setting.json", systemsettings); + //reset value shown in menu to the newly set one + submenu_calibrate.Offset.value = getInitialCalibrationOffset(); + E.showMenu(mainmenu); + } + }); + } + }; + + var submenu_chargewarn = { + '': { + title: "Charge warning" + }, + '< Back': function() { + E.showMenu(mainmenu); + }, + 'Enabled': { + value: !!settings.warnEnabled, + format: v => settings.warnEnabled ? "On" : "Off", + onchange: v => { + writeSettings("warnEnabled", v); + } + }, + 'Percentage': { + min: 80, + max: 100, + step: 2, + value: settings.warn, + format: v => v + "%", + onchange: v => { + writeSettings("warn", v); + } + } + }; + + E.showMenu(mainmenu); +})