bthrm 0.11: App now shows status info while connecting

+      Fixes to allow cached BluetoothRemoteGATTCharacteristic to work with 2v14.14 onwards (>1 central)
pull/2016/head
Gordon Williams 2022-07-01 11:01:27 +01:00
parent ae3f61b13c
commit 20d5bae555
4 changed files with 46 additions and 31 deletions

View File

@ -23,3 +23,5 @@
0.08: Allow scanning for devices in settings 0.08: Allow scanning for devices in settings
0.09: Misc Fixes and improvements (https://github.com/espruino/BangleApps/pull/1655) 0.09: Misc Fixes and improvements (https://github.com/espruino/BangleApps/pull/1655)
0.10: Use default Bangle formatter for booleans 0.10: Use default Bangle formatter for booleans
0.11: App now shows status info while connecting
Fixes to allow cached BluetoothRemoteGATTCharacteristic to work with 2v14.14 onwards (>1 central)

View File

@ -5,11 +5,11 @@
); );
var log = function(text, param){ var log = function(text, param){
if (global.showStatusInfo)
showStatusInfo(text)
if (settings.debuglog){ if (settings.debuglog){
var logline = new Date().toISOString() + " - " + text; var logline = new Date().toISOString() + " - " + text;
if (param){ if (param) logline += ": " + JSON.stringify(param);
logline += " " + JSON.stringify(param);
}
print(logline); print(logline);
} }
}; };
@ -30,7 +30,7 @@
}; };
var addNotificationHandler = function(characteristic) { var addNotificationHandler = function(characteristic) {
log("Setting notification handler: " + supportedCharacteristics[characteristic.uuid].handler); log("Setting notification handler"/*supportedCharacteristics[characteristic.uuid].handler*/);
characteristic.on('characteristicvaluechanged', (ev) => supportedCharacteristics[characteristic.uuid].handler(ev.target.value)); characteristic.on('characteristicvaluechanged', (ev) => supportedCharacteristics[characteristic.uuid].handler(ev.target.value));
}; };
@ -61,7 +61,8 @@
writeCache(cache); writeCache(cache);
}; };
var characteristicsFromCache = function() { var characteristicsFromCache = function(device) {
var service = { device : device }; // fake a BluetoothRemoteGATTService
log("Read cached characteristics"); log("Read cached characteristics");
var cache = getCache(); var cache = getCache();
if (!cache.characteristics) return []; if (!cache.characteristics) return [];
@ -75,6 +76,7 @@
r.properties = {}; r.properties = {};
r.properties.notify = cached.notify; r.properties.notify = cached.notify;
r.properties.read = cached.read; r.properties.read = cached.read;
r.service = service;
addNotificationHandler(r); addNotificationHandler(r);
log("Restored characteristic: ", r); log("Restored characteristic: ", r);
restored.push(r); restored.push(r);
@ -141,7 +143,7 @@
src: "bthrm" src: "bthrm"
}; };
log("Emitting HRM: ", repEvent); log("Emitting HRM", repEvent);
Bangle.emit("HRM", repEvent); Bangle.emit("HRM", repEvent);
} }
@ -155,7 +157,7 @@
if (battery) newEvent.battery = battery; if (battery) newEvent.battery = battery;
if (sensorContact) newEvent.contact = sensorContact; if (sensorContact) newEvent.contact = sensorContact;
log("Emitting BTHRM: ", newEvent); log("Emitting BTHRM", newEvent);
Bangle.emit("BTHRM", newEvent); Bangle.emit("BTHRM", newEvent);
} }
}, },
@ -257,8 +259,8 @@
var buzzing = false; var buzzing = false;
var onDisconnect = function(reason) { var onDisconnect = function(reason) {
log("Disconnect: " + reason); log("Disconnect: " + reason);
log("GATT: ", gatt); log("GATT", gatt);
log("Characteristics: ", characteristics); log("Characteristics", characteristics);
retryTime = initialRetryTime; retryTime = initialRetryTime;
clearRetryTimeout(); clearRetryTimeout();
switchInternalHrm(); switchInternalHrm();
@ -273,13 +275,13 @@
}; };
var createCharacteristicPromise = function(newCharacteristic) { var createCharacteristicPromise = function(newCharacteristic) {
log("Create characteristic promise: ", newCharacteristic); log("Create characteristic promise", newCharacteristic);
var result = Promise.resolve(); var result = Promise.resolve();
// For values that can be read, go ahead and read them, even if we might be notified in the future // For values that can be read, go ahead and read them, even if we might be notified in the future
// Allows for getting initial state of infrequently updating characteristics, like battery // Allows for getting initial state of infrequently updating characteristics, like battery
if (newCharacteristic.readValue){ if (newCharacteristic.readValue){
result = result.then(()=>{ result = result.then(()=>{
log("Reading data for " + JSON.stringify(newCharacteristic)); log("Reading data", newCharacteristic);
return newCharacteristic.readValue().then((data)=>{ return newCharacteristic.readValue().then((data)=>{
if (supportedCharacteristics[newCharacteristic.uuid] && supportedCharacteristics[newCharacteristic.uuid].handler) { if (supportedCharacteristics[newCharacteristic.uuid] && supportedCharacteristics[newCharacteristic.uuid].handler) {
supportedCharacteristics[newCharacteristic.uuid].handler(data); supportedCharacteristics[newCharacteristic.uuid].handler(data);
@ -289,8 +291,8 @@
} }
if (newCharacteristic.properties.notify){ if (newCharacteristic.properties.notify){
result = result.then(()=>{ result = result.then(()=>{
log("Starting notifications for: ", newCharacteristic); log("Starting notifications", newCharacteristic);
var startPromise = newCharacteristic.startNotifications().then(()=>log("Notifications started for ", newCharacteristic)); var startPromise = newCharacteristic.startNotifications().then(()=>log("Notifications started", newCharacteristic));
if (settings.gracePeriodNotification > 0){ if (settings.gracePeriodNotification > 0){
log("Add " + settings.gracePeriodNotification + "ms grace period after starting notifications"); log("Add " + settings.gracePeriodNotification + "ms grace period after starting notifications");
startPromise = startPromise.then(()=>{ startPromise = startPromise.then(()=>{
@ -301,7 +303,7 @@
return startPromise; return startPromise;
}); });
} }
return result.then(()=>log("Handled characteristic: ", newCharacteristic)); return result.then(()=>log("Handled characteristic", newCharacteristic));
}; };
var attachCharacteristicPromise = function(promise, characteristic) { var attachCharacteristicPromise = function(promise, characteristic) {
@ -312,11 +314,11 @@
}; };
var createCharacteristicsPromise = function(newCharacteristics) { var createCharacteristicsPromise = function(newCharacteristics) {
log("Create characteristics promise: ", newCharacteristics); log("Create characteristics promis ", newCharacteristics);
var result = Promise.resolve(); var result = Promise.resolve();
for (var c of newCharacteristics){ for (var c of newCharacteristics){
if (!supportedCharacteristics[c.uuid]) continue; if (!supportedCharacteristics[c.uuid]) continue;
log("Supporting characteristic: ", c); log("Supporting characteristic", c);
characteristics.push(c); characteristics.push(c);
if (c.properties.notify){ if (c.properties.notify){
addNotificationHandler(c); addNotificationHandler(c);
@ -328,10 +330,10 @@
}; };
var createServicePromise = function(service) { var createServicePromise = function(service) {
log("Create service promise: ", service); log("Create service promise", service);
var result = Promise.resolve(); var result = Promise.resolve();
result = result.then(()=>{ result = result.then(()=>{
log("Handling service: " + service.uuid); log("Handling service" + service.uuid);
return service.getCharacteristics().then((c)=>createCharacteristicsPromise(c)); return service.getCharacteristics().then((c)=>createCharacteristicsPromise(c));
}); });
return result.then(()=>log("Handled service" + service.uuid)); return result.then(()=>log("Handled service" + service.uuid));
@ -368,7 +370,7 @@
} }
promise = promise.then((d)=>{ promise = promise.then((d)=>{
log("Got device: ", d); log("Got device", d);
d.on('gattserverdisconnected', onDisconnect); d.on('gattserverdisconnected', onDisconnect);
device = d; device = d;
}); });
@ -379,14 +381,14 @@
}); });
} else { } else {
promise = Promise.resolve(); promise = Promise.resolve();
log("Reuse device: ", device); log("Reuse device", device);
} }
promise = promise.then(()=>{ promise = promise.then(()=>{
if (gatt){ if (gatt){
log("Reuse GATT: ", gatt); log("Reuse GATT", gatt);
} else { } else {
log("GATT is new: ", gatt); log("GATT is new", gatt);
characteristics = []; characteristics = [];
var cachedId = getCache().id; var cachedId = getCache().id;
if (device.id !== cachedId){ if (device.id !== cachedId){
@ -404,7 +406,10 @@
promise = promise.then((gatt)=>{ promise = promise.then((gatt)=>{
if (!gatt.connected){ if (!gatt.connected){
var connectPromise = gatt.connect(connectSettings); log("Connecting...");
var connectPromise = gatt.connect(connectSettings).then(function() {
log("Connected.");
});
if (settings.gracePeriodConnect > 0){ if (settings.gracePeriodConnect > 0){
log("Add " + settings.gracePeriodConnect + "ms grace period after connecting"); log("Add " + settings.gracePeriodConnect + "ms grace period after connecting");
connectPromise = connectPromise.then(()=>{ connectPromise = connectPromise.then(()=>{
@ -432,7 +437,7 @@
promise = promise.then(()=>{ promise = promise.then(()=>{
if (!characteristics || characteristics.length === 0){ if (!characteristics || characteristics.length === 0){
characteristics = characteristicsFromCache(); characteristics = characteristicsFromCache(device);
} }
}); });
@ -445,11 +450,11 @@
}); });
characteristicsPromise = characteristicsPromise.then((services)=>{ characteristicsPromise = characteristicsPromise.then((services)=>{
log("Got services:", services); log("Got services", services);
var result = Promise.resolve(); var result = Promise.resolve();
for (var service of services){ for (var service of services){
if (!(supportedServices.includes(service.uuid))) continue; if (!(supportedServices.includes(service.uuid))) continue;
log("Supporting service: ", service.uuid); log("Supporting service", service.uuid);
result = attachServicePromise(result, service); result = attachServicePromise(result, service);
} }
if (settings.gracePeriodService > 0) { if (settings.gracePeriodService > 0) {
@ -496,7 +501,7 @@
log("Power off for " + app); log("Power off for " + app);
if (gatt) { if (gatt) {
if (gatt.connected){ if (gatt.connected){
log("Disconnect with gatt: ", gatt); log("Disconnect with gatt", gatt);
try{ try{
gatt.disconnect().then(()=>{ gatt.disconnect().then(()=>{
log("Successful disconnect"); log("Successful disconnect");

View File

@ -42,12 +42,20 @@ function draw(y, type, event) {
if (event.energy) str += " kJoule: " + event.energy.toFixed(0); if (event.energy) str += " kJoule: " + event.energy.toFixed(0);
g.setFontVector(12).drawString(str,px,y+60); g.setFontVector(12).drawString(str,px,y+60);
} }
} }
var firstEventBt = true; var firstEventBt = true;
var firstEventInt = true; var firstEventInt = true;
// This can get called for the boot code to show what's happening
function showStatusInfo(txt) {
var R = Bangle.appRect;
g.reset().clearRect(R.x,R.y2-24,R.x2,R.y2).setFont("6x8");
txt = g.wrapString(txt, R.w)[0];
g.setFontAlign(0,1).drawString(txt, (R.x+R.x2)/2, R.y2);
}
function onBtHrm(e) { function onBtHrm(e) {
if (firstEventBt){ if (firstEventBt){
clear(24); clear(24);

View File

@ -2,7 +2,7 @@
"id": "bthrm", "id": "bthrm",
"name": "Bluetooth Heart Rate Monitor", "name": "Bluetooth Heart Rate Monitor",
"shortName": "BT HRM", "shortName": "BT HRM",
"version": "0.10", "version": "0.11",
"description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.",
"icon": "app.png", "icon": "app.png",
"type": "app", "type": "app",