From d49809920a322af8e21638d38380a85e9453b124 Mon Sep 17 00:00:00 2001 From: Elfreda Kwawu Date: Fri, 5 Apr 2024 22:57:04 -0400 Subject: [PATCH] adding files to phystrax --- apps/phystrax/app-icon.js | 1 + apps/phystrax/app.js | 114 +++++++++++++++++++++++++++++++++++ apps/phystrax/app.png | Bin 0 -> 1950 bytes apps/phystrax/interface.html | 64 ++++++++++++++++++++ apps/phystrax/metadata.json | 14 +++++ 5 files changed, 193 insertions(+) create mode 100644 apps/phystrax/app-icon.js create mode 100644 apps/phystrax/app.js create mode 100644 apps/phystrax/app.png create mode 100644 apps/phystrax/interface.html create mode 100644 apps/phystrax/metadata.json diff --git a/apps/phystrax/app-icon.js b/apps/phystrax/app-icon.js new file mode 100644 index 000000000..a535bf5e3 --- /dev/null +++ b/apps/phystrax/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwZC/AH4ABgVJkmAA4cEyVJCIwIBkmSAwUBAoIIBCAgaCBYNIA4IFCFgwIDF4Q7CBAWQFg4CBkESCIg+DhIRFAQ9ACKYOLMRWf5IRQ/IRP/4RlzwRKyf5k4RC/xcFCISPBKwMn+YRB/4RFUImf/4RCEwIRIa4P/AAPz/YRDHwLXEgP//1P/+T/8vJQIZCCIkAn/yCIOSv8/2YQCCIOQCIY+CCIYmB8g1CCIkECIM8CII4CLIeACIcAMQd//mSvYRDCAkAiQRFWYcgCIsCCJIQFbQl/8jCGAAq2ByVPCIiwCAAq2BCILCECA6SEAQaMEAAqSCRhIAFCIoQKSQiMHQBJ6IQBB6IQBAQNNwRoLAH4AoA=")) \ No newline at end of file diff --git a/apps/phystrax/app.js b/apps/phystrax/app.js new file mode 100644 index 000000000..663652c14 --- /dev/null +++ b/apps/phystrax/app.js @@ -0,0 +1,114 @@ +let isMeasuring = false; +let currentHeartRate = null; +let lcdTimeout; +let logData = []; + +function startMeasure() { + isMeasuring = true; + Bangle.setLCDTimeout(0); + lcdTimeout = setTimeout(() => { + Bangle.setLCDTimeout(50); + }, 50000); + + setTimeout(() => { + Bangle.setHRMPower(1); + Bangle.on('HRM', handleHeartRate); + Bangle.beep(400, 1000); // Buzz to indicate measurement start + drawScreen(); + }, 500); +} + +function stopMeasure() { + isMeasuring = false; + clearTimeout(lcdTimeout); + Bangle.setLCDTimeout(10); + Bangle.setHRMPower(0); + Bangle.removeAllListeners('HRM'); + saveDataToCSV(); // Save data to CSV when measurement stops + Bangle.beep(400, 800); // Buzz to indicate measurement stop + drawScreen(); +} + +function handleHeartRate(hrm) { + if (hrm.confidence > 90) { + currentHeartRate = hrm.bpm; + let date = new Date(); + let dateStr = require("locale").date(date); + let timeStr = require("locale").time(date, 1); + let seconds = date.getSeconds(); + let timestamp = `${dateStr} ${timeStr}:${seconds}`; // Concatenate date, time, and seconds + logData.push({ timestamp: timestamp, heartRate: currentHeartRate }); + drawScreen(); + } +} + + +function drawScreen(message) { + g.clear(); // Clear the display + + // Set the background color + g.setColor('#95E7FF'); + + // Fill the entire display with the background color + g.fillRect(0, 0, g.getWidth(), g.getHeight()); + + // Set font and alignment for drawing text + g.setFontAlign(0, 0); + g.setFont('Vector', 15); + + // Draw the title + g.setColor('#000000'); // Set text color to black + g.drawString('Heart Rate Monitor', g.getWidth() / 2, 10); + + if (isMeasuring) { + // Draw measuring status + g.setFont('6x8', 2); + g.drawString('Measuring...', g.getWidth() / 2, g.getHeight() / 2 - 10); + + // Draw current heart rate if available + g.setFont('6x8', 4); + if (currentHeartRate !== null) { + g.drawString(currentHeartRate.toString(), g.getWidth() / 2, g.getHeight() / 2 + 20); + g.setFont('6x8', 1.6); + g.drawString(' BPM', g.getWidth() / 2 + 42, g.getHeight() / 2 + 20); + } + + // Draw instructions + g.setFont('6x8', 1.5); + g.drawString('Press button to stop', g.getWidth() / 2, g.getHeight() / 2 + 42); + } else { + // Draw last heart rate + g.setFont('Vector', 12); + g.drawString('Last Heart Rate:', g.getWidth() / 2, g.getHeight() / 2 - 20); + if (currentHeartRate !== null && currentHeartRate > 0) { + g.setFont('6x8', 4); + g.drawString(currentHeartRate.toString(), g.getWidth() / 2, g.getHeight() / 2 + 10); + } else { + g.setFont('6x8', 2); + g.drawString('No data', g.getWidth() / 2, g.getHeight() / 2 + 10); + g.setFont('6x8', 1); + g.drawString(message || 'Press button to start', g.getWidth() / 2, g.getHeight() / 2 + 30); + } + } + + // Update the display + g.flip(); +} + +function saveDataToCSV() { + let csvContent = "Timestamp,Heart Rate\n"; + logData.forEach(entry => { + csvContent += `${entry.timestamp},${entry.heartRate}\n`; + }); + require("Storage").write("heart_rate_data.csv", csvContent); +} + +setWatch(function() { + if (!isMeasuring) { + startMeasure(); + } else { + stopMeasure(); + } +}, BTN1, { repeat: true, edge: 'rising' }); + +drawScreen(); diff --git a/apps/phystrax/app.png b/apps/phystrax/app.png new file mode 100644 index 0000000000000000000000000000000000000000..b9c10ca4683a987b0056826fd952fd97d97d289d GIT binary patch literal 1950 zcmV;P2VwY$P)0`}qCd@3SS6deoyH^{B_?4$d*z%{iy`a4zpG z=kSu8!@I)TCrHjdd6=_r-IEv|m#+7o^q^Bl6Rt;T!g-i6I!MakSfTZHk~WOY()y7< zQaW4LMT0Y=6U_gNt;Dpo2 z5Y7)7!UYWB1lq`_189Q-XuTaJr5k~mZX`o#Z8Nmi+_)k5#ORHdgwspsz%l$}7M=&s z!?U(=lyR#k!&=7E(cG`cx=KbCNI(1dHgnsrK-2aomhX@ywd5JWYW zWK>;a5x8x#;0&td~y< zL^WoJ^q69_dZ?kgedp9`h1Ms^TelWk$KV*AF^!_62VF}v;aaNQx^)e_1!5WtMAc@9 zs!b5>F+oI09I9d3cr%r)dqk}>rY!s*pJm#mob>^lsC5M2V}ht^5F#o9!b&0&Q|db_ z6ySZd>>{mb-3{#cc1TSBJ`2BgkrrDQYZt3vJz8WP!7B-fD2zB|`rYCM*eCw85$nm1 zjsQd`;C4=L+`6W`bpc*(fUwK}VX1Cbv;cNwB2d}-nnjxJb=JEBARI#lEbe&%!y7he zy@$8XgBMvx@OlVK^$_aTk>UjmZ(R`^jpcjY1xx?@H-hJL>0bvoXx&uUF2&Xnybi+G zYa!IFT@fuHZu10dv7TR~E=V0aAr!Fs&U@>yZmwuOEME(rgCBrkSHEBU6R>$^Yq6f2 zFzhXNVfauKJ*JKxFR{)&@CYm)dJ`z4<6^8ssA~X1UHuU3>_0622@H)rUa}#X-N4;` zKV;5dfTh1ZRWM0kudozr;27@d$leGa|Ozn1ytTXfAhyg+4-0qmW-g!Wo_ z>)k5W^=Ofnv(Cc@xAZ}Z*GGj# zy0~vYq`y3cr_F&EVEL6d@b%Nrp>|oGc?-A7Bafp+N*SGy@dZ)g>62%0ad+%0Yn{36 zen|iCETm7J1$xIc2Jh?>tOqx1Q2N_?JXH&TnVBCYkDcIh=8)x6^FW(MfxC4YFW68N z^*e%^+=0w4{(V0#X#ex5*SUuu!;|U#PhsINPvQ4ooB?Wd8>G*k7w!#3nL0V22hYK` zt9kf2kVvkQ)DkPtAM)lVONIOAgnfLd%Yj%U*7|%Q}d8Ic?PJP?-HyB+W72& zK&x`ky5LbO>GeOR^}`>R+mLAYO|bCie*mSo3&(&M;mnTGAT0d#X>`r6i(IcS?tcLn z;15B}b8~)?b{6$|JGPF%H>tqisyqS;#nqCHM3fl$1vOv`)Oz?zpToVK>v3l1y~2c{ zT-zXZ{3Ngs?JXIN!7O|pJPY5VB*X2BYb6&G{I3K2_tIJpU#lO_<`@3ya}ee?r*a!o z73+ak6_Cw}xUW^U?q55~7ooB0W169*YR7=(mtPkOSa|Z;iW`!s^;RYLTNF$FR+&z6 zDI=mbIU_yhWTj(3;)y4P0{C%Rx*@H#t}e0eZ&3o-B2W1nm1CC_UMNCknu@3fSH+G2 z@wL%UfSF8cVG!foxK&l1);tVHk?DU;HV%35#DTlY6BfNYd=z9!k=_W~~z(WRA#y0yN_ zhp!6On-$=1mV>`he!+L$^_OPath)$>_S#Tq|D4$2tGsm{9JLIPjj}I%&B|X%e#n?_ zvHm2`(RZ-;@KtDCS!f->OAmebOU+LuS4xE1H8%y@)r(cFH^`RB2I+LoC(G|Md@a2) z|0dPEsPzWf8Q*o?GRc)3k+!~T$X3ORMZM0$zxs8PqU2}yD>nR1itYS_AseLM`5L6# ke`ub1)T18tkX)AdKh$!^8g*v#$^ZZW07*qoM6N<$f^2=ns{jB1 literal 0 HcmV?d00001 diff --git a/apps/phystrax/interface.html b/apps/phystrax/interface.html new file mode 100644 index 000000000..d2d3a89cc --- /dev/null +++ b/apps/phystrax/interface.html @@ -0,0 +1,64 @@ + + + + + +
+ + + + + + + diff --git a/apps/phystrax/metadata.json b/apps/phystrax/metadata.json new file mode 100644 index 000000000..e4198919b --- /dev/null +++ b/apps/phystrax/metadata.json @@ -0,0 +1,14 @@ +{ "id": "phystrax", + "name": "PhysTrax", + "shortName":"PhysTrax", + "icon": "app.png", + "version":"0.01", + "description": "Tracking physiological measurements to support active learning in classrooms", + "tags": "health", + "interface": "interface.html", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"phystrax.app.js","url":"app.js"}, + {"name":"phystrax.img","url":"app-icon.js","evaluate":true} + ] +} \ No newline at end of file