forked from FOSS/BangleApps
commit
48d24623a3
|
@ -40,3 +40,4 @@
|
|||
0.16: Set powerdownRequested correctly on BTHRM power on
|
||||
Additional logging on errors
|
||||
Add debug option for disabling active scanning
|
||||
0.17: New GUI based on layout library
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
var intervalInt;
|
||||
var intervalBt;
|
||||
const BPM_FONT_SIZE="19%";
|
||||
const VALUE_TIMEOUT=3000;
|
||||
|
||||
var BODY_LOCS = {
|
||||
0: 'Other',
|
||||
|
@ -7,46 +7,119 @@ var BODY_LOCS = {
|
|||
2: 'Wrist',
|
||||
3: 'Finger',
|
||||
4: 'Hand',
|
||||
5: 'Ear Lobe',
|
||||
5: 'Earlobe',
|
||||
6: 'Foot',
|
||||
};
|
||||
|
||||
var Layout = require("Layout");
|
||||
|
||||
function border(l,c) {
|
||||
g.setColor(c).drawLine(l.x+l.w*0.05, l.y-4, l.x+l.w*0.95, l.y-4);
|
||||
}
|
||||
|
||||
function clear(y){
|
||||
g.reset();
|
||||
g.clearRect(0,y,g.getWidth(),y+75);
|
||||
}
|
||||
|
||||
function draw(y, type, event) {
|
||||
clear(y);
|
||||
var px = g.getWidth()/2;
|
||||
var str = event.bpm + "";
|
||||
g.reset();
|
||||
g.setFontAlign(0,0);
|
||||
g.setFontVector(40).drawString(str,px,y+20);
|
||||
str = "Event: " + type;
|
||||
if (type === "HRM") {
|
||||
str += " Confidence: " + event.confidence;
|
||||
g.setFontVector(12).drawString(str,px,y+40);
|
||||
str = " Source: " + (event.src ? event.src : "internal");
|
||||
g.setFontVector(12).drawString(str,px,y+50);
|
||||
function getRow(id, text, additionalInfo){
|
||||
let additional = [];
|
||||
let l = {
|
||||
type:"h", c: [
|
||||
{
|
||||
type:"v",
|
||||
width: g.getWidth()*0.4,
|
||||
c: [
|
||||
{type:"txt", halign:1, font:"8%", label:text, id:id+"text" },
|
||||
{type:"txt", halign:1, font:BPM_FONT_SIZE, label:"--", id:id, bgCol: g.theme.bg }
|
||||
]
|
||||
},{
|
||||
type:undefined, fillx:1
|
||||
},{
|
||||
type:"v",
|
||||
valign: -1,
|
||||
width: g.getWidth()*0.45,
|
||||
c: additional
|
||||
},{
|
||||
type:undefined, width:g.getWidth()*0.05
|
||||
}
|
||||
]
|
||||
};
|
||||
for (let i of additionalInfo){
|
||||
let label = {type:"txt", font:"6x8", label:i + ":" };
|
||||
let value = {type:"txt", font:"6x8", label:"--", id:id + i };
|
||||
additional.push({type:"h", halign:-1, c:[ label, {type:undefined, fillx:1}, value ]});
|
||||
}
|
||||
if (type === "BTHRM"){
|
||||
if (event.battery) str += " Bat: " + (event.battery ? event.battery : "");
|
||||
g.setFontVector(12).drawString(str,px,y+40);
|
||||
str= "";
|
||||
if (event.location) str += "Loc: " + BODY_LOCS[event.location];
|
||||
if (event.rr && event.rr.length > 0) str += " RR: " + event.rr.join(",");
|
||||
g.setFontVector(12).drawString(str,px,y+50);
|
||||
str= "";
|
||||
if (event.contact) str += " Contact: " + event.contact;
|
||||
if (event.energy) str += " kJoule: " + event.energy.toFixed(0);
|
||||
g.setFontVector(12).drawString(str,px,y+60);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
var layout = new Layout( {
|
||||
type:"v", c: [
|
||||
getRow("int", "INT", ["Confidence"]),
|
||||
getRow("agg", "HRM", ["Confidence", "Source"]),
|
||||
getRow("bt", "BT", ["Battery","Location","Contact", "RR", "Energy"]),
|
||||
{ type:undefined, height:8 } //dummy to protect debug output
|
||||
]
|
||||
}, {
|
||||
lazy:true
|
||||
});
|
||||
|
||||
var int,agg,bt;
|
||||
var firstEvent = true;
|
||||
|
||||
function draw(){
|
||||
if (!(int || agg || bt)) return;
|
||||
|
||||
if (firstEvent) {
|
||||
g.clearRect(Bangle.appRect);
|
||||
firstEvent = false;
|
||||
}
|
||||
|
||||
let now = Date.now();
|
||||
|
||||
if (int && int.time > (now - VALUE_TIMEOUT)){
|
||||
layout.int.label = int.bpm;
|
||||
if (!isNaN(int.confidence)) layout.intConfidence.label = int.confidence;
|
||||
} else {
|
||||
layout.int.label = "--";
|
||||
layout.intConfidence.label = "--";
|
||||
}
|
||||
|
||||
if (agg && agg.time > (now - VALUE_TIMEOUT)){
|
||||
layout.agg.label = agg.bpm;
|
||||
if (!isNaN(agg.confidence)) layout.aggConfidence.label = agg.confidence;
|
||||
if (agg.src) layout.aggSource.label = agg.src;
|
||||
} else {
|
||||
layout.agg.label = "--";
|
||||
layout.aggConfidence.label = "--";
|
||||
layout.aggSource.label = "--";
|
||||
}
|
||||
|
||||
if (bt && bt.time > (now - VALUE_TIMEOUT)) {
|
||||
layout.bt.label = bt.bpm;
|
||||
if (!isNaN(bt.battery)) layout.btBattery.label = bt.battery + "%";
|
||||
if (bt.rr) layout.btRR.label = bt.rr.join(",");
|
||||
if (!isNaN(bt.location)) layout.btLocation.label = BODY_LOCS[bt.location];
|
||||
if (bt.contact !== undefined) layout.btContact.label = bt.contact ? "Yes":"No";
|
||||
if (!isNaN(bt.energy)) layout.btEnergy.label = bt.energy.toFixed(0) + "kJ";
|
||||
} else {
|
||||
layout.bt.label = "--";
|
||||
layout.btBattery.label = "--";
|
||||
layout.btRR.label = "--";
|
||||
layout.btLocation.label = "--";
|
||||
layout.btContact.label = "--";
|
||||
layout.btEnergy.label = "--";
|
||||
}
|
||||
|
||||
layout.update();
|
||||
layout.render();
|
||||
let first = true;
|
||||
for (let c of layout.l.c){
|
||||
if (first) {
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
if (c.type && c.type == "h")
|
||||
border(c,g.theme.fg);
|
||||
}
|
||||
}
|
||||
|
||||
var firstEventBt = true;
|
||||
var firstEventInt = true;
|
||||
|
||||
|
||||
// This can get called for the boot code to show what's happening
|
||||
function showStatusInfo(txt) {
|
||||
|
@ -57,41 +130,26 @@ function showStatusInfo(txt) {
|
|||
}
|
||||
|
||||
function onBtHrm(e) {
|
||||
if (firstEventBt){
|
||||
clear(24);
|
||||
firstEventBt = false;
|
||||
}
|
||||
draw(100, "BTHRM", e);
|
||||
if (e.bpm === 0){
|
||||
Bangle.buzz(100,0.2);
|
||||
}
|
||||
if (intervalBt){
|
||||
clearInterval(intervalBt);
|
||||
}
|
||||
intervalBt = setInterval(()=>{
|
||||
clear(100);
|
||||
}, 2000);
|
||||
bt = e;
|
||||
bt.time = Date.now();
|
||||
}
|
||||
|
||||
function onHrm(e) {
|
||||
if (firstEventInt){
|
||||
clear(24);
|
||||
firstEventInt = false;
|
||||
}
|
||||
draw(24, "HRM", e);
|
||||
if (intervalInt){
|
||||
clearInterval(intervalInt);
|
||||
}
|
||||
intervalInt = setInterval(()=>{
|
||||
clear(24);
|
||||
}, 2000);
|
||||
function onInt(e) {
|
||||
int = e;
|
||||
int.time = Date.now();
|
||||
}
|
||||
|
||||
function onAgg(e) {
|
||||
agg = e;
|
||||
agg.time = Date.now();
|
||||
}
|
||||
|
||||
var settings = require('Storage').readJSON("bthrm.json", true) || {};
|
||||
|
||||
Bangle.on('BTHRM', onBtHrm);
|
||||
Bangle.on('HRM', onHrm);
|
||||
Bangle.on('HRM_int', onInt);
|
||||
Bangle.on('HRM', onAgg);
|
||||
|
||||
|
||||
Bangle.setHRMPower(1,'bthrm');
|
||||
if (!(settings.startWithHrm)){
|
||||
|
@ -103,10 +161,11 @@ Bangle.loadWidgets();
|
|||
Bangle.drawWidgets();
|
||||
if (Bangle.setBTHRMPower){
|
||||
g.reset().setFont("6x8",2).setFontAlign(0,0);
|
||||
g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2 - 24);
|
||||
g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2);
|
||||
setInterval(draw, 1000);
|
||||
} else {
|
||||
g.reset().setFont("6x8",2).setFontAlign(0,0);
|
||||
g.drawString("BTHRM disabled",g.getWidth()/2,g.getHeight()/2 + 32);
|
||||
g.drawString("BTHRM disabled",g.getWidth()/2,g.getHeight()/2);
|
||||
}
|
||||
|
||||
E.on('kill', ()=>Bangle.setBTHRMPower(0,'bthrm'));
|
||||
|
|
|
@ -553,14 +553,15 @@ exports.enable = () => {
|
|||
|
||||
if (settings.replace){
|
||||
// register a listener for original HRM events and emit as HRM_int
|
||||
Bangle.on("HRM", (e) => {
|
||||
e.modified = true;
|
||||
Bangle.on("HRM", (o) => {
|
||||
let e = Object.assign({},o);
|
||||
log("Emitting HRM_int", e);
|
||||
Bangle.emit("HRM_int", e);
|
||||
if (fallbackActive){
|
||||
// if fallback to internal HRM is active, emit as HRM_R to which everyone listens
|
||||
log("Emitting HRM_R(int)", e);
|
||||
Bangle.emit("HRM_R", e);
|
||||
o.src = "int";
|
||||
log("Emitting HRM_R(int)", o);
|
||||
Bangle.emit("HRM_R", o);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -576,6 +577,13 @@ exports.enable = () => {
|
|||
if (name == "HRM") o("HRM_R", cb);
|
||||
else o(name, cb);
|
||||
})(Bangle.removeListener);
|
||||
} else {
|
||||
Bangle.on("HRM", (o)=>{
|
||||
o.src = "int";
|
||||
let e = Object.assign({},o);
|
||||
log("Emitting HRM_int", e);
|
||||
Bangle.emit("HRM_int", e);
|
||||
});
|
||||
}
|
||||
|
||||
Bangle.origSetHRMPower = Bangle.setHRMPower;
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
"id": "bthrm",
|
||||
"name": "Bluetooth Heart Rate Monitor",
|
||||
"shortName": "BT HRM",
|
||||
"version": "0.16",
|
||||
"version": "0.17",
|
||||
"description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screen.png"}],
|
||||
"type": "app",
|
||||
"tags": "health,bluetooth,hrm,bthrm",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
Loading…
Reference in New Issue