forked from FOSS/BangleApps
Added first version of CRP Assist app
parent
76b51f5074
commit
6ca8262b51
25
apps.json
25
apps.json
|
@ -2033,5 +2033,30 @@
|
|||
{"name":"widancs.wid.js","url":"ancs.min.js"},
|
||||
{"name":"widancs.settings.js","url":"settings.js"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cprassist",
|
||||
"name":"CPR Assist",
|
||||
"icon":"cprassist-icon.png",
|
||||
"version": "0.01",
|
||||
"readme": "README.md",
|
||||
"description": "Provides assistance while performing a CPR",
|
||||
"tags": "tool,firstaid",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{
|
||||
"name": "cprassist.app.js",
|
||||
"url": "cprassist.js"
|
||||
},
|
||||
{
|
||||
"name": "cprassist.img",
|
||||
"url": "cprassist-icon.js",
|
||||
"evaluate": true
|
||||
},
|
||||
{
|
||||
"name": "cprassist.settings.js",
|
||||
"url": "settings.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
|
@ -0,0 +1,24 @@
|
|||
# CPR Assist
|
||||
|
||||
Provides assistance while performing a CPR
|
||||
|
||||
## Usage
|
||||
|
||||
The app alternates between the phases for
|
||||
chest compression and rescue breaths in an in an endless loop.
|
||||
In the chest compression phase the the watch will provide a
|
||||
buzz at a rate of 100 rpm for 30 repetitions.
|
||||
A longer buzz introduces an interval of 4 seconds to perform
|
||||
2 rescue breaths.
|
||||
A ratio of chest compressions to rescue breaths is also
|
||||
displayed in the bottom of the screen.
|
||||
|
||||
The number of repetitions for chest compression and
|
||||
rescue breaths, the rpm rate and the duration of the
|
||||
rescue breath phase can be adjusted in the settings.
|
||||
See e.g. [CPR on Wikipedia](https://en.wikipedia.org/wiki/Cardiopulmonary_resuscitation)
|
||||
for futher information and updates on the recommendations.
|
||||
|
||||
## Attributions
|
||||
|
||||
Icon source: https://commons.wikimedia.org/wiki/File:ISO_7010_E003_-_First_aid_sign.svg
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwhC/AH4Arg93AB1wC/dxkQACi4XRuf/AAU3C/4X/C+sTmYABn4XD+YICmIXJl4TDAA/yC/4X/C+LXXAAdzC4c3BQgX/C/4X0uMiAAUXC6IAKC+wA/AH4AkA=="))
|
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
|
@ -0,0 +1,79 @@
|
|||
const SETTINGS_FILE = 'cprassist.settings.json';
|
||||
const SHORT_BUZZ_PERIOD = 80;
|
||||
const LONG_BUZZ_PERIOD = 800;
|
||||
|
||||
Bangle.setLCDTimeout(undefined); // do not deaktivate display while running this app
|
||||
|
||||
let settings;
|
||||
|
||||
function setting(key) {
|
||||
const DEFAULTS = {
|
||||
'compression_count': 30,
|
||||
'breath_count': 2,
|
||||
'compression_rpm': 100,
|
||||
'breath_period_sec': 4
|
||||
};
|
||||
if (!settings) {
|
||||
const storage = require("Storage");
|
||||
settings = storage.readJSON(SETTINGS_FILE, 1) || {};
|
||||
}
|
||||
return (key in settings)
|
||||
? settings[key]
|
||||
: DEFAULTS[key];
|
||||
}
|
||||
|
||||
let counter = setting('compression_count');
|
||||
|
||||
function provideFeedback() {
|
||||
let period = counter > 0
|
||||
? SHORT_BUZZ_PERIOD
|
||||
: LONG_BUZZ_PERIOD;
|
||||
try {
|
||||
Bangle.buzz(period, 1.0);
|
||||
} catch(err) {
|
||||
}
|
||||
}
|
||||
|
||||
function drawHeart() {
|
||||
g.fillCircle(40, 92, 12);
|
||||
g.fillCircle(60, 92, 12);
|
||||
g.fillPoly([29, 98, 50, 120, 71, 98]);
|
||||
}
|
||||
|
||||
function updateScreen() {
|
||||
const colors = [0xFFFF, 0x9492];
|
||||
g.reset().clearRect(0, 50, 250, 150);
|
||||
if (counter > 0) {
|
||||
g.setFont("Vector", 40).setFontAlign(0, 0);
|
||||
g.setColor(colors[counter%2]);
|
||||
drawHeart();
|
||||
g.drawString(counter + "", g.getWidth()/2, 100);
|
||||
} else {
|
||||
g.setFont("Vector", 20).setFontAlign(0, 0);
|
||||
g.drawString("RESCUE", g.getWidth()/2, 70);
|
||||
g.drawString("BREATHS", g.getWidth()/2, 120);
|
||||
}
|
||||
}
|
||||
|
||||
function tick() {
|
||||
provideFeedback();
|
||||
updateScreen();
|
||||
if (counter == 0) {
|
||||
var reset = function() {
|
||||
counter = setting('compression_count');
|
||||
clearInterval(interval);
|
||||
interval = setInterval(tick, 60000/setting('compression_rpm'));
|
||||
};
|
||||
clearInterval(interval);
|
||||
interval = setInterval(reset, setting('breath_period_sec')*1000);
|
||||
}
|
||||
counter -= 1;
|
||||
}
|
||||
|
||||
interval = setInterval(tick, 60000/setting('compression_rpm'));
|
||||
|
||||
g.clear(1).setFont("6x8");
|
||||
g.drawString(setting('compression_count') + ' / ' + setting('breath_count'), 30, 200);
|
||||
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
|
@ -0,0 +1,64 @@
|
|||
// This file should contain exactly one function, which shows the app's settings
|
||||
/**
|
||||
* @param {function} back Use back() to return to settings menu
|
||||
*/
|
||||
(function(back) {
|
||||
const SETTINGS_FILE = 'cprassist.settings.json';
|
||||
|
||||
// initialize with default settings...
|
||||
let s = {
|
||||
'compression_count': 30,
|
||||
'breath_count': 2,
|
||||
'compression_rpm': 100,
|
||||
'breath_period_sec': 4
|
||||
};
|
||||
// ...and overwrite them with any saved values
|
||||
// This way saved values are preserved if a new version adds more settings
|
||||
const storage = require('Storage');
|
||||
const saved = storage.readJSON(SETTINGS_FILE, 1) || {};
|
||||
for (const key in saved) {
|
||||
s[key] = saved[key];
|
||||
}
|
||||
|
||||
// creates a function to safe a specific setting
|
||||
function save(key) {
|
||||
return function(value) {
|
||||
s[key] = value;
|
||||
storage.write(SETTINGS_FILE, s);
|
||||
};
|
||||
}
|
||||
|
||||
const menu = {
|
||||
'': { 'title': 'CPR Assist' },
|
||||
'< Back': back,
|
||||
'chest compr.': {
|
||||
value: s.compression_count,
|
||||
min: 1,
|
||||
max: 200,
|
||||
step: 1,
|
||||
onchange: save('compression_count'),
|
||||
},
|
||||
'rescue breaths': {
|
||||
value: s.breath_count,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
onchange: save('breath_count'),
|
||||
},
|
||||
'rpm': {
|
||||
value: s.compression_rpm,
|
||||
min: 1,
|
||||
max: 200,
|
||||
step: 10,
|
||||
onchange: save('compression_rpm'),
|
||||
},
|
||||
'breaths period': {
|
||||
value: s.breath_period_sec,
|
||||
min: 1,
|
||||
max: 60,
|
||||
step: 1,
|
||||
onchange: save('breath_period_sec'),
|
||||
}
|
||||
};
|
||||
E.showMenu(menu);
|
||||
});
|
Loading…
Reference in New Issue