diff --git a/apps/widbattpwr/ChangeLog b/apps/widbattpwr/ChangeLog new file mode 100644 index 000000000..b1bdaa6fc --- /dev/null +++ b/apps/widbattpwr/ChangeLog @@ -0,0 +1 @@ +0.01: Initial fork from hwid_a_battery_widget diff --git a/apps/widbattpwr/README.md b/apps/widbattpwr/README.md new file mode 100644 index 000000000..4dd4c8a5a --- /dev/null +++ b/apps/widbattpwr/README.md @@ -0,0 +1,11 @@ +# Battery Power Widget + +Show the time remaining at the current power consumption, and battery percentage via shading of the text and a percentage bar. + +Requires firmware 2v23 or above. + +This is a copy of `hwid_a_battery_widget` (that being a copy of `wid_a_battery_widget`). + +## Creator + +[@bobrippling](https://github.com/bobrippling) diff --git a/apps/widbattpwr/metadata.json b/apps/widbattpwr/metadata.json new file mode 100644 index 000000000..667485666 --- /dev/null +++ b/apps/widbattpwr/metadata.json @@ -0,0 +1,19 @@ +{ + "id": "widbattpwr", + "name": "Battery power and percentage widget", + "shortName": "Batt Pwr", + "icon": "widget.png", + "version": "0.01", + "type": "widget", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "description": "A battery widget showing percentage (via shading) and time remaining at current power consumption", + "tags": "widget,battery", + "provides_widgets": ["battery"], + "storage": [ + { + "name": "widbattpwr.wid.js", + "url": "widget.js" + } + ] +} diff --git a/apps/widbattpwr/widget.js b/apps/widbattpwr/widget.js new file mode 100644 index 000000000..b6c0924d1 --- /dev/null +++ b/apps/widbattpwr/widget.js @@ -0,0 +1,60 @@ +(function () { + var intervalLow = 60000; + var intervalHigh = 2000; + var width = 30; + var height = 24; + var powerColour = function (pwr) { + return pwr >= 23000 + ? "#f00" + : pwr > 2000 + ? "#fc0" + : "#0f0"; + }; + var drawBar = function (x, y, batt) { + return g.fillRect(x + 1, y + height - 3, x + 1 + (width - 2) * batt / 100, y + height - 1); + }; + var drawString = function (x, y, txt) { + return g.drawString(txt, x + 14, y + 10); + }; + function draw() { + var x = this.x; + var y = this.y; + var batt = E.getBattery(); + var pwr = E.getPowerUsage(); + var usage = 0; + for (var key in pwr.device) { + if (!/^(LCD|LED)/.test(key)) + usage += pwr.device[key]; + } + var pwrColour = powerColour(usage); + g.reset() + .setBgColor(g.theme.bg) + .clearRect(x, y, x + width - 1, y + height - 1); + g.setColor(g.theme.fg); + drawBar(x, y, 100); + g.setColor(pwrColour); + drawBar(x, y, batt); + g.setFontAlign(0, 0); + g.setFont("Vector", 16); + { + var hrs = 200000 / usage; + var days = hrs / 24; + var txt = days >= 1 ? "".concat(Math.round(Math.min(days, 99)), "d") : "".concat(Math.round(hrs), "h"); + var txth = 14; + g.setColor(g.theme.fg); + g.setClipRect(x, y, x + width, y + txth); + drawString(x, y, txt); + g.setColor(pwrColour); + g.setClipRect(x, y + txth * (1 - batt / 100), x + width, y + txth); + drawString(x, y, txt); + } + } + var id = setInterval(function () { + var w = WIDGETS["battpwr"]; + w.draw(w); + }, intervalLow); + Bangle.on("charging", function (charging) { + changeInterval(id, charging ? intervalHigh : intervalLow); + }); + WIDGETS["battpwr"] = { area: "tr", width: width, draw: draw }; +})(); diff --git a/apps/widbattpwr/widget.png b/apps/widbattpwr/widget.png new file mode 100644 index 000000000..e5a8284a1 Binary files /dev/null and b/apps/widbattpwr/widget.png differ diff --git a/apps/widbattpwr/widget.ts b/apps/widbattpwr/widget.ts new file mode 100644 index 000000000..b39412179 --- /dev/null +++ b/apps/widbattpwr/widget.ts @@ -0,0 +1,71 @@ +(() => { + const intervalLow = 60000; + const intervalHigh = 2000; + const width = 30; + const height = 24; + + const powerColour = (pwr: number) => + pwr >= 23000 + ? "#f00" // red, e.g. GPS ~20k + : pwr > 2000 + ? "#fc0" // yellow, e.g. CPU ~1k, HRM ~700 + : "#0f0"; // green: ok + + const drawBar = (x: number, y: number, batt: number) => + g.fillRect(x+1, y+height-3, x+1+(width-2)*batt/100, y+height-1); + + const drawString = (x: number, y: number, txt: string) => + g.drawString(txt, x + 14, y + 10); + + function draw(this: Widget) { + let x = this.x!; + let y = this.y!; + + const batt = E.getBattery(); + const pwr = E.getPowerUsage(); + let usage = 0; + for(const key in pwr.device){ + if(!/^(LCD|LED)/.test(key)) + usage += pwr.device[key]; + } + const pwrColour = powerColour(usage); + + g.reset() + .setBgColor(g.theme.bg) + .clearRect(x, y, x + width - 1, y + height - 1); + + g.setColor(g.theme.fg); + drawBar(x, y, 100); + g.setColor(pwrColour); + drawBar(x, y, batt); + + g.setFontAlign(0, 0); + g.setFont("Vector", 16); + { + const hrs = 200000 / usage; + const days = hrs / 24; + const txt = days >= 1 ? `${Math.round(Math.min(days, 99))}d` : `${Math.round(hrs)}h`; + + // draw time remaining, then shade it based on batt % + const txth = 14; + g.setColor(g.theme.fg); + g.setClipRect(x, y, x + width, y + txth); + drawString(x, y, txt); + + g.setColor(pwrColour); + g.setClipRect(x, y + txth * (1 - batt / 100), x + width, y + txth); + drawString(x, y, txt); + } + } + + const id = setInterval(() => { + const w = WIDGETS["battpwr"]!; + w.draw(w); + }, intervalLow); + + Bangle.on("charging", charging => { + changeInterval(id, charging ? intervalHigh : intervalLow); + }); + + WIDGETS["battpwr"] = { area: "tr", width, draw }; +})();