cscsensor 0.06: Now read wheel rev as well as cadence sensor

Improve connection code
master
Gordon Williams 2021-11-26 10:04:02 +00:00
parent 095165c5c9
commit a4299586e8
4 changed files with 86 additions and 74 deletions

View File

@ -2948,7 +2948,7 @@
"id": "cscsensor", "id": "cscsensor",
"name": "Cycling speed sensor", "name": "Cycling speed sensor",
"shortName": "CSCSensor", "shortName": "CSCSensor",
"version": "0.05", "version": "0.06",
"description": "Read BLE enabled cycling speed and cadence sensor and display readings on watch", "description": "Read BLE enabled cycling speed and cadence sensor and display readings on watch",
"icon": "icons8-cycling-48.png", "icon": "icons8-cycling-48.png",
"tags": "outdoors,exercise,ble,bluetooth", "tags": "outdoors,exercise,ble,bluetooth",

View File

@ -3,3 +3,5 @@
0.03: Save total distance traveled 0.03: Save total distance traveled
0.04: Add sensor battery level indicator 0.04: Add sensor battery level indicator
0.05: Add cadence sensor support 0.05: Add cadence sensor support
0.06: Now read wheel rev as well as cadence sensor
Improve connection code

View File

@ -16,3 +16,9 @@ If the watch app has not received an update from the sensor for at least 10 seco
Button 2 switches between the display for cycling speed and cadence. Button 2 switches between the display for cycling speed and cadence.
Values displayed are imperial or metric (depending on locale), cadence is in RPM, the wheel circumference can be adjusted in the global settings app. Values displayed are imperial or metric (depending on locale), cadence is in RPM, the wheel circumference can be adjusted in the global settings app.
# TODO
* Use Layout Library to provide proper Bangle.js 2 support
* Turn CSC sensor support into a library
* Support for `Recorder` app, to allow CSC readings to be logged alongside GPS

View File

@ -5,6 +5,8 @@ var characteristic;
const SETTINGS_FILE = 'cscsensor.json'; const SETTINGS_FILE = 'cscsensor.json';
const storage = require('Storage'); const storage = require('Storage');
const W = g.getWidth();
const H = g.getHeight();
class CSCSensor { class CSCSensor {
constructor() { constructor() {
@ -152,7 +154,7 @@ class CSCSensor {
var qChanged = false; var qChanged = false;
if (event.target.uuid == "0x2a5b") { if (event.target.uuid == "0x2a5b") {
if (event.target.value.getUint8(0, true) & 0x2) { if (event.target.value.getUint8(0, true) & 0x2) {
// crank revolution // crank revolution - if enabled
const crankRevs = event.target.value.getUint16(1, true); const crankRevs = event.target.value.getUint16(1, true);
const crankTime = event.target.value.getUint16(3, true); const crankTime = event.target.value.getUint16(3, true);
if (crankTime > this.lastCrankTime) { if (crankTime > this.lastCrankTime) {
@ -161,7 +163,7 @@ class CSCSensor {
} }
this.lastCrankRevs = crankRevs; this.lastCrankRevs = crankRevs;
this.lastCrankTime = crankTime; this.lastCrankTime = crankTime;
} else { }
// wheel revolution // wheel revolution
var wheelRevs = event.target.value.getUint32(1, true); var wheelRevs = event.target.value.getUint32(1, true);
var dRevs = (this.lastRevs>0 ? wheelRevs-this.lastRevs : 0); var dRevs = (this.lastRevs>0 ? wheelRevs-this.lastRevs : 0);
@ -199,7 +201,6 @@ class CSCSensor {
this.lastSpeed = this.speed; this.lastSpeed = this.speed;
if (this.speed>this.maxSpeed && (this.movingTime>3 || this.speed<20) && this.speed<50) this.maxSpeed = this.speed; if (this.speed>this.maxSpeed && (this.movingTime>3 || this.speed<20) && this.speed<50) this.maxSpeed = this.speed;
} }
}
if (qChanged && this.qUpdateScreen) this.updateScreen(); if (qChanged && this.qUpdateScreen) this.updateScreen();
} }
} }
@ -215,12 +216,16 @@ function getSensorBatteryLevel(gatt) {
}); });
} }
function parseDevice(d) { function connection_setup() {
mySensor.screenInit = true;
E.showMessage("Scanning for CSC sensor...");
NRF.requestDevice({ filters: [{services:["1816"]}]}).then(function(d) {
device = d; device = d;
g.clearRect(0, 60, 239, 239).setFontAlign(0, 0, 0).setColor(0, 1, 0).drawString("Found device", 120, 120).flip(); E.showMessage("Found device");
device.gatt.connect().then(function(ga) { return device.gatt.connect();
}).then(function(ga) {
gatt = ga; gatt = ga;
g.clearRect(0, 60, 239, 239).setFontAlign(0, 0, 0).setColor(0, 1, 0).drawString("Connected", 120, 120).flip(); E.showMessage("Connected");
return gatt.getPrimaryService("1816"); return gatt.getPrimaryService("1816");
}).then(function(s) { }).then(function(s) {
service = s; service = s;
@ -231,28 +236,27 @@ function parseDevice(d) {
return characteristic.startNotifications(); return characteristic.startNotifications();
}).then(function() { }).then(function() {
console.log("Done!"); console.log("Done!");
g.clearRect(0, 60, 239, 239).setColor(1, 1, 1).flip(); g.reset().clearRect(Bangle.appRect).flip();
getSensorBatteryLevel(gatt); getSensorBatteryLevel(gatt);
mySensor.updateScreen(); mySensor.updateScreen();
}).catch(function(e) { }).catch(function(e) {
g.clearRect(0, 60, 239, 239).setColor(1, 0, 0).setFontAlign(0, 0, 0).drawString("ERROR"+e, 120, 120).flip(); E.showMessage(e.toString(), "ERROR");
console.log(e); console.log(e);
})} });
function connection_setup() {
NRF.setScan();
mySensor.screenInit = true;
NRF.setScan(parseDevice, { filters: [{services:["1816"]}], timeout: 2000});
g.clearRect(0, 48, 239, 239).setFontVector(18).setFontAlign(0, 0, 0).setColor(0, 1, 0);
g.drawString("Scanning for CSC sensor...", 120, 120);
} }
connection_setup(); connection_setup();
setWatch(function() { mySensor.reset(); g.clearRect(0, 48, 239, 239); mySensor.updateScreen(); }, BTN1, {repeat:true, debounce:20}); E.on('kill',()=>{
E.on('kill',()=>{ if (gatt!=undefined) gatt.disconnect(); mySensor.settings.totaldist = mySensor.totaldist; storage.writeJSON(SETTINGS_FILE, mySensor.settings); }); if (gatt!=undefined) gatt.disconnect();
setWatch(function() { if (Date.now()-mySensor.lastBangleTime>10000) connection_setup(); }, BTN3, {repeat:true, debounce:20}); mySensor.settings.totaldist = mySensor.totaldist;
setWatch(function() { mySensor.toggleDisplayCadence(); g.clearRect(0, 48, 239, 239); mySensor.updateScreen(); }, BTN2, {repeat:true, debounce:20}); storage.writeJSON(SETTINGS_FILE, mySensor.settings);
NRF.on('disconnect', connection_setup); });
NRF.on('disconnect', connection_setup); // restart if disconnected
Bangle.setUI("updown", d=>{
if (d<0) { mySensor.reset(); g.clearRect(0, 48, W, H); mySensor.updateScreen(); }
if (d==0) { if (Date.now()-mySensor.lastBangleTime>10000) connection_setup(); }
if (d>0) { mySensor.toggleDisplayCadence(); g.clearRect(0, 48, W, H); mySensor.updateScreen(); }
});
Bangle.loadWidgets(); Bangle.loadWidgets();
Bangle.drawWidgets(); Bangle.drawWidgets();