From 7caac64a8653f06f95650228abc98018de8df9b8 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 30 Nov 2021 20:40:33 +0100 Subject: [PATCH] widbars: new widget --- apps.json | 17 +++++++++- apps/widbars/ChangeLog | 1 + apps/widbars/README.md | 14 ++++++++ apps/widbars/icon.png | Bin 0 -> 2294 bytes apps/widbars/screenshot.png | Bin 0 -> 2377 bytes apps/widbars/widget.js | 62 ++++++++++++++++++++++++++++++++++++ 6 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 apps/widbars/ChangeLog create mode 100644 apps/widbars/README.md create mode 100644 apps/widbars/icon.png create mode 100644 apps/widbars/screenshot.png create mode 100644 apps/widbars/widget.js diff --git a/apps.json b/apps.json index 2e338a432..bca8d6cbd 100644 --- a/apps.json +++ b/apps.json @@ -4557,5 +4557,20 @@ { "name": "sensible.app.js", "url": "sensible.js" }, { "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true } ] -} +}, + { + "id": "widbars", + "name": "Bars Widget", + "version": "0.01", + "description": "Display several measurements as vertical bars.", + "icon": "icon.png", + "screenshots": [{"url":"screenshot.png"}], + "readme": "README.md", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widbars.wid.js","url":"widget.js"} + ] + } ] diff --git a/apps/widbars/ChangeLog b/apps/widbars/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/widbars/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/widbars/README.md b/apps/widbars/README.md new file mode 100644 index 000000000..eba5cc347 --- /dev/null +++ b/apps/widbars/README.md @@ -0,0 +1,14 @@ +# Bars Widget + +A simple widget that display several measurements as vertical bars. + +![Screenshot](screenshot.png) + +## Measurements from left to right: + +- Current heart rate, on a scale from 0-200 bpm (*red*)
+ Only if available: this widget does not turn on HRM monitoring by itself. +- Device temperature, on a scale from 0-50 °C (*yellow*) +- Flash storage space used (*blue/cyan*) +- Memory usage (*magenta*) +- Battery charge (*green*) \ No newline at end of file diff --git a/apps/widbars/icon.png b/apps/widbars/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..59f78d66623a8aaf97376d6290bbfba9afcfe99b GIT binary patch literal 2294 zcmV zaB^>EX>4U6ba`-PAZ2)IW&i+q+Ra#5mg6=I{O2ih1QJ|89)}y=%MEh;6i7*4#-3?s z`X#a2qRa&aqOeeH=3jq``2!!~l1+%5Q%T9<6G|vl@sREQly!GDto!=-V+g+=`pq>! z=<>IjT#xw`{qeTo#BlAg-{fP2@*&7wg0}{Wtk2_KN%Yh1ci|9J=6*;e^S!F=5Y&%} zOO@jrF12=}zs*Aj!%8Cp$P-QPyj}OaHSqd%zT&HQ@7Fx^YELp~f*>k(RF8iDWXp8e2oEm@Tzu;H7YseQ!=Vv94zzp`^MjE^Mi!ZScQqtf zG#wtbjO|V_nAl))zm_FjjBmsaI8fD`H%5!&N74uC}`l6$4FT zv_u_5X1~djwmo9GMmW9_{2JN)Eytmb|^p&jvra zj7V1#Ih!wAK`&Cjh8oJ8-Z2Y=I5~KW%fRP#&~NYj2d)YR<1(|dS8dxOT68zx@{4DW zc@ganA!m3T0$?IwM<|032+k(wqf5>*5jzJvW)M`NIr%^h47eC+KuHSTCo)W#6dP;U zt+^B_k#-|DY54f$8Qc_KK~@M6{=*@|hiddO#28cLm`yCPCZ9rzDJ4#tHmFIXE|=lWu7N1@u(dPE=QRLTZlYjOMC_Wvcw zmn=qdm=fT3WjZc`J#$CG6s;qHr4w_F@Jg|*Yj49eZF8;SN2NBsm&V>W9x!|7$wOvy z)3;WoWeK#VA1J8#8)u=wzz-;3LCgZ$FegZsIeL%6__Ls-bDndyIWd@YFF=AC$XWlI zv3-wqBllsYXS=%LNRrB$(y(6-Kf7CK@;9mUTF^gG$eihHFeo|7(#s1_$w0@O8-=7H3To9PntLe~#fHNVjL%c`2Ux_+pt`P{6p zRW+ZR^|fI0xmjPg=5w>&2JEVTIE=MU21P4a8Hr_z)*$IP7NIo3>!(|xP%Te{r6xfBTr!U$q*)xLofM_d)SiP!4qdPN{=#N`Nd2&z~- zjFh}8X`Ye$#QEz$*Z^*hnGm+|+#BH}_RcZ!jQ~OCKQNa z`&D!M&;=QI6&)d=qw-GIIHBv-AR9Wjtf#WlM32B-W~zE-6I2G7wEf>Rd`-m}a55qg zW%hM8?CO%y)$Udufn!3o&H- z{Mu@DiCT${6(VbTcoJ&z5fjI9jR_FA*cfgFk49}L4Q^+5aAVtu$28aGtY5*cmDc8T zL^s|Ac66hz4PPEMm)q==c03*!CxX6Ln-c^-_Ca?6fvXeh#MvlQUz_e|(JERBtf2q( ztI7%0hQk8bg%)77NiO>G7?*2Q2@nO}8bMJfX*yBTVW^4s`qsqYY(9KLX7e2+FY57j z_b45kJ>;wRJZBMm}1n0+8UUYwsnH@ z=WD~Fn@8Oq?4x94!-SM34S(=aym&}t?{FGfK2uO~UL$=K$Sfq?%LRkIM7S6y9Bm5T zH+LLsuDHebkF9w(@M-&@AnX{iV*Uok=WuD3z2z?e00D$)LqkwWLqi~Na&Km7Y-Iod zc$|HaJxIeq9K~N#rJ@ywb`TNCP@OD@iaKf)icq1{3avVrT>1q~8j=(jN5Qq=;KyRs z!Nplu2UkH5`~Y!tb5eAX691PJTEuv8+>dwn9(V5mpttSBkO z=ftB1U6A;Z>$1yloC^*MJTq*hQ}e`OVzJQ1avQUvp%PCLM-)|~d?Dkq!g-6cTCTF@ zJ^2fRIc;T`>of-u$0C-Hga{c`lu(9+D6JYPCQ`H?^Y9Ni{v^3%a+Scyv49FxNRA); z4}N!R<|oG8q+kr_e6j71VIZ&zG-|f}eQeu}6TtrrTxl(Tr4Gz|l3r_Rkt3jQ8@RY` zY4RR$xdZe+>5?HilAorK&jasg^i5eHbPIH^xxF>_arywHsjI{daBv8W6exS$RA}Dq+5rlHAPfc2ExP}e*99CAMJBzS zz~^u1q^zn~xwcrm0A|u{3p#T5? literal 0 HcmV?d00001 diff --git a/apps/widbars/screenshot.png b/apps/widbars/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..146e085e3bd42a99fc342e62a86a5a88471d815a GIT binary patch literal 2377 zcmds({Xf%tAICr6&D^Yn6Sg{}uW+Wd%@-kDD{7>M;5WfELo7^xF{{MV===J7l_=ls%g~)}MQy zb|o5e$Mz}5CJH!L=dLyA>}<37sHm>4F0fj@$EZLI0&|&BP>TTwBwm97qg4J24P1l> zsEqR6pr@933BszEte7VkG;xd|A{hcXT&Co|h>GGg)%MTl`K94Ykc1gVw0z=ZoURt= zpn9jVTJTk`(-1J~mi8MHK)D;yAAp`2t0ZLrqy2Pa62|Q(mU9U;%nZT9^6Wf5rgMU}brkmY_fuaia;?Uw&JVy9Fdy*1G>dNPcxq z4$h@YhV`XuFYC5zF`lpfrN0FYc98a&MH@=;czR7QuDNz$@L=IwQTIi(QX)@k3sPIi zD!6hFF{n1MD$@}PPr>Fnp;ZTcmhX(jF$lccicT+0Ox~0y`AaSY5E5@SuJpX zr{kL$bS!ruz=3m-_j=*gL+Uh2;y0YSln;7M^;`ADZ}wlR#yYL<$^pjC@{Qg{Iw=c| zfTDfOYNUIL^%lzzRba;GwgPtHp0-*~vwX{)z=$zKgz#%c2JsBdPGG)f zG9xKEAVqc5?n^wfx?)++cNiy4G-&nTUgSnjCwd6O*^s3zO<}E}i<}Ic^ShQ9$;6?cg7_jp2z6 zG|CRv$15EXCUF(br#-*zy)Y?Yi`y!X9~+8Sued`Kncu!Ohn)1VO%~=t!7kWZUAHfJ zc~qCIX)KsH(tYX?FE8d(bnUwOP1d4JW6w>U5F;-*;ouB6#`EVW*a<_M5sBTajQV~? z8qnbTQnO(j<12XU$ola=I>|ciW*Ard)}j^5nJ@k-v@C1(Awzl2`IZdo41r%Qp^oHJd>#g4DcY@^9LM8C)4 z>-=p9xFk|xl;C&+hu&r@;QxgZKI|Ra*1ku5oPWClRV})yvnJ8WiaCJ`4r8A@jOI9vwf#ugwM2Z`}BjlljiRR#+JHv$>onbpQ2$d*)6GmcdpP zzC&1$Q|LP9;ZmNw>_RG{3VnQQaO4L3!ZC%o&WL?pJD@Fe>3FMVFzc{DjTYsbSSTQ@ z^d{`FX?Izn%hR0`1ayQ>&1_J_`wqu8!i_AN=c(UHbeqlo(Hjj>GaWj`3v z-)=WQbxf%THtq2*cOVQu2szXur9a*U;j|10CN<54hmNI$EK;7^|BCl?fmsJ=l$$rt zBq+bLN?nPkEi&i-wk98I-8@>&}I;P&YJ+a%zP2 z{Fd>(;yC`Flo(Dz(XHK|nnyNPX4`qO2MhsI@+j(7T{H)^`|yA)!x|BGZhW>QAWLx{ z_Cg#Vq3aj;C7BaB<3S9IK=R95-rc-}cF9`~N9>&0+@|0Niap*p9De;Tr%GkdhN=n2 z+US+@WMblZ<&Q_8uIer@=E>os;acJAJ~d7&57bp&ue(RSBCPy7)|_LP#OEcSaFJc@ zve}Ft+BTaXB{a& { + const h=24, // widget height + w=3, // width of single bar + bars=3; // number of bars + + // We show HRM if available, but don't turn it on + let bpm,rst,con=10; // always ignore HRM with confidence below 10% + function noHrm() { // last value is no longer valid + if (rst) clearTimeout(rst); + rst=bpm=undefined; con=10; + WIDGETS["bars"].draw(); + } + Bangle.on('HRM', hrm=>{ + if (hrm.confidence>con || hrm.confidence>=80) { + bpm=hrm.confidence; + con=hrm.confidence; + WIDGETS["bars"].draw(); + if (rst) clearTimeout(rst); + rst = setTimeout(noHrm, 10*60*1000); // forget HRM after 10 minutes + } + }); + + /** + * Draw a bar + * + * @param {int} x left + * @param {int} y top (of full bar) + * @param {string} col Color + * @param {number} f Fraction of bar to draw + */ + function bar(x,y, col,f) { + if (!f) f = 0; // for f=NaN: set it to 0 -> don't even draw the bottom pixel + if (f>1) f = 1; + if (f<0) f = 0; + const top = Math.round((h-1)*(1-f)); + // use Math.min/max to make sure we stay within widget boundaries for f=0/f=1 + if (top) g .clearRect(x,y, x+w-1,y+top-1); // erase above bar + if (f) g.setColor(col).fillRect(x,y+top, x+w-1,y+h-1); // even for f=0.001 this is still 1 pixel high + } + function draw() { + g.reset(); + const x = this.x, y = this.y, + m = process.memory(); + let b=0; + bar(x+(w*b++),y,'#f00'/*red */,bpm/200); // >200 seems very unhealthy; if we have no valid bpm this will just be empty space + bar(x+(w*b++),y,'#ff0'/*yellow */,E.getTemperature()/50); // you really don't want to wear a watch that's hotter than 50°C + bar(x+(w*b++),y,g.theme.dark?'#0ff':'#00f'/*cyan/blue*/,1-(require('Storage').getFree() / process.env.STORAGE)); + bar(x+(w*b++),y,'#f0f'/*magenta*/,m.usage/m.total); + bar(x+(w*b++),y,'#0f0'/*green */,E.getBattery()/100); + } + + let redraw; + Bangle.on('lcdPower', on => { + if (redraw) clearInterval(redraw) + redraw = undefined; + if (on) { + WIDGETS["bars"].draw(); + redraw = setInterval(()=>WIDGETS["bars"].draw, 10*1000); // redraw every 10 seconds + } + }); + WIDGETS["bars"]={area:"tr",width: bars*w,draw:draw}; +})()