Move BLE advertising coordination to a module

pull/3420/head
Rob Pilling 2024-05-17 08:52:32 +01:00
parent f8aab1d6b7
commit 2a4057666b
17 changed files with 129 additions and 71 deletions

View File

@ -16,3 +16,4 @@ apps/rep/
apps/widChargingStatus/ apps/widChargingStatus/
apps/widbtstates/ apps/widbtstates/
apps/widhid/ apps/widhid/
modules/ble_advert.js

View File

@ -1,2 +1,3 @@
0.01: Initial release. 0.01: Initial release.
0.02: Handle the case where other apps have set bleAdvert to an array 0.02: Handle the case where other apps have set bleAdvert to an array
0.03: Use the bleAdvert module

View File

@ -1,26 +1,8 @@
(() => { (() => {
function advertiseBattery() { function advertiseBattery() {
if(Array.isArray(Bangle.bleAdvert)){ require("ble_advert").set(0x180F, [E.getBattery()]);
// ensure we're in the cycle
var found = false;
for(var ad in Bangle.bleAdvert){
if(ad[0x180F]){
ad[0x180F] = [E.getBattery()];
found = true;
break;
}
}
if(!found)
Bangle.bleAdvert.push({ 0x180F: [E.getBattery()] });
}else{
// simple object
Bangle.bleAdvert[0x180F] = [E.getBattery()];
}
NRF.setAdvertising(Bangle.bleAdvert);
} }
if (!Bangle.bleAdvert) Bangle.bleAdvert = {};
setInterval(advertiseBattery, 60 * 1000); setInterval(advertiseBattery, 60 * 1000);
advertiseBattery(); advertiseBattery();
})(); })();

View File

@ -2,7 +2,7 @@
"id": "bootgattbat", "id": "bootgattbat",
"name": "BLE GATT Battery Service", "name": "BLE GATT Battery Service",
"shortName": "BLE Battery Service", "shortName": "BLE Battery Service",
"version": "0.02", "version": "0.03",
"description": "Adds the GATT Battery Service to advertise the percentage of battery currently remaining over Bluetooth.\n", "description": "Adds the GATT Battery Service to advertise the percentage of battery currently remaining over Bluetooth.\n",
"icon": "bluetooth.png", "icon": "bluetooth.png",
"type": "bootloader", "type": "bootloader",

View File

@ -1,3 +1,4 @@
0.01: Initial release. 0.01: Initial release.
0.02: Added compatibility to OpenTracks and added HRM Location 0.02: Added compatibility to OpenTracks and added HRM Location
0.03: Allow setting to keep BLE connected 0.03: Allow setting to keep BLE connected
0.04: Use the bleAdvert module

View File

@ -4,18 +4,13 @@
* This function prepares BLE heart rate Advertisement. * This function prepares BLE heart rate Advertisement.
*/ */
NRF.setAdvertising( require("ble_advert").set(0x180d, undefined, {
{ // We need custom Advertisement settings for Apps like OpenTracks
0x180d: undefined connectable: true,
}, discoverable: true,
{ scannable: true,
// We need custom Advertisement settings for Apps like OpenTracks whenConnected: true,
connectable: true, });
discoverable: true,
scannable: true,
whenConnected: true,
}
);
NRF.setServices({ NRF.setServices({
0x180D: { // heart_rate 0x180D: { // heart_rate
@ -28,7 +23,6 @@
} }
} }
}); });
} }
const keepConnected = (require("Storage").readJSON("gatthrm.settings.json", 1) || {}).keepConnected; const keepConnected = (require("Storage").readJSON("gatthrm.settings.json", 1) || {}).keepConnected;

View File

@ -2,7 +2,7 @@
"id": "bootgatthrm", "id": "bootgatthrm",
"name": "BLE GATT HRM Service", "name": "BLE GATT HRM Service",
"shortName": "BLE HRM Service", "shortName": "BLE HRM Service",
"version": "0.03", "version": "0.04",
"description": "Adds the GATT HRM Service to advertise the measured HRM over Bluetooth.\n", "description": "Adds the GATT HRM Service to advertise the measured HRM over Bluetooth.\n",
"icon": "bluetooth.png", "icon": "bluetooth.png",
"type": "bootloader", "type": "bootloader",

View File

@ -666,6 +666,8 @@ const getBleAdvert = <T>(map: (s: BleServ) => T, all = false) => {
// done via advertise in setServices() // done via advertise in setServices()
//const updateBleAdvert = () => { //const updateBleAdvert = () => {
// require("ble_advert").set(...)
//
// let bleAdvert: ReturnType<typeof getBleAdvert<undefined>>; // let bleAdvert: ReturnType<typeof getBleAdvert<undefined>>;
// //
// if (!(bleAdvert = (Bangle as any).bleAdvert)) { // if (!(bleAdvert = (Bangle as any).bleAdvert)) {

View File

@ -3,3 +3,4 @@
0.03: Cope with identical duplicate buttons (fix #3260) 0.03: Cope with identical duplicate buttons (fix #3260)
Set 'n' for buttons in Bangle.btHomeData correctly (avoids adding extra buttons on end of advertising) Set 'n' for buttons in Bangle.btHomeData correctly (avoids adding extra buttons on end of advertising)
0.04: Fix duplicate button on edit->save 0.04: Fix duplicate button on edit->save
0.05: Use the bleAdvert module

View File

@ -1,5 +1,3 @@
// Ensure we have the bleAdvert global (to play well with other stuff)
if (!Bangle.bleAdvert) Bangle.bleAdvert = {};
Bangle.btHomeData = []; Bangle.btHomeData = [];
{ {
require("BTHome").packetId = 0|(Math.random()*256); // random packet id so new packets show up require("BTHome").packetId = 0|(Math.random()*256); // random packet id so new packets show up
@ -39,20 +37,6 @@ Bangle.btHome = function(extras, options) {
if (bat) bat.v = E.getBattery(); if (bat) bat.v = E.getBattery();
var advert = require("BTHome").getAdvertisement(Bangle.btHomeData)[0xFCD2]; var advert = require("BTHome").getAdvertisement(Bangle.btHomeData)[0xFCD2];
// Add to the list of available advertising // Add to the list of available advertising
if(Array.isArray(Bangle.bleAdvert)){
var found = false;
for(var ad in Bangle.bleAdvert){
if(ad[0xFCD2]){
ad[0xFCD2] = advert;
found = true;
break;
}
}
if(!found)
Bangle.bleAdvert.push({ 0xFCD2: advert });
} else {
Bangle.bleAdvert[0xFCD2] = advert;
}
var advOptions = {}; var advOptions = {};
var updateTimeout = 10*60*1000; // update every 10 minutes var updateTimeout = 10*60*1000; // update every 10 minutes
if (options.event) { // if it's an event... if (options.event) { // if it's an event...
@ -60,7 +44,7 @@ Bangle.btHome = function(extras, options) {
advOptions.whenConnected = true; advOptions.whenConnected = true;
updateTimeout = 30000; // slow down in 30 seconds updateTimeout = 30000; // slow down in 30 seconds
} }
NRF.setAdvertising(Bangle.bleAdvert, advOptions); require("ble_advert").set(0xFCD2, advert, advOptions);
if (Bangle.btHomeTimeout) clearTimeout(Bangle.btHomeTimeout); if (Bangle.btHomeTimeout) clearTimeout(Bangle.btHomeTimeout);
Bangle.btHomeTimeout = setTimeout(function() { Bangle.btHomeTimeout = setTimeout(function() {
delete Bangle.btHomeTimeout; delete Bangle.btHomeTimeout;

View File

@ -1,7 +1,7 @@
{ "id": "bthome", { "id": "bthome",
"name": "BTHome", "name": "BTHome",
"shortName":"BTHome", "shortName":"BTHome",
"version":"0.04", "version":"0.05",
"description": "Allow your Bangle to advertise with BTHome and send events to Home Assistant via Bluetooth", "description": "Allow your Bangle to advertise with BTHome and send events to Home Assistant via Bluetooth",
"icon": "icon.png", "icon": "icon.png",
"type": "app", "type": "app",

View File

@ -1,2 +1,3 @@
0.01: New App! 0.01: New App!
0.02: Handle the case where other apps have set bleAdvert to an array 0.02: Handle the case where other apps have set bleAdvert to an array
0.03: Use the bleAdvert module

View File

@ -38,21 +38,7 @@ function onTemperature(p) {
pressure100&255,(pressure100>>8)&255,pressure100>>16 pressure100&255,(pressure100>>8)&255,pressure100>>16
]; ];
if(Array.isArray(Bangle.bleAdvert)){ require("ble_advert").set(0xFCD2, advert);
var found = false;
for(var ad in Bangle.bleAdvert){
if(ad[0xFCD2]){
ad[0xFCD2] = advert;
found = true;
break;
}
}
if(!found)
Bangle.bleAdvert.push({ 0xFCD2: advert });
}else{
Bangle.bleAdvert[0xFCD2] = advert;
}
NRF.setAdvertising(Bangle.bleAdvert);
} }
// Gets the temperature in the most accurate way with pressure sensor // Gets the temperature in the most accurate way with pressure sensor
@ -60,7 +46,6 @@ function drawTemperature() {
Bangle.getPressure().then(p =>{if (p) onTemperature(p);}); Bangle.getPressure().then(p =>{if (p) onTemperature(p);});
} }
if (!Bangle.bleAdvert) Bangle.bleAdvert = {};
setInterval(function() { setInterval(function() {
drawTemperature(); drawTemperature();
}, 10000); // update every 10s }, 10000); // update every 10s

View File

@ -1,7 +1,7 @@
{ "id": "bthometemp", { "id": "bthometemp",
"name": "BTHome Temperature and Pressure", "name": "BTHome Temperature and Pressure",
"shortName":"BTHome T", "shortName":"BTHome T",
"version":"0.02", "version":"0.03",
"description": "Displays temperature and pressure, and advertises them over bluetooth for Home Assistant using BTHome.io standard", "description": "Displays temperature and pressure, and advertises them over bluetooth for Home Assistant using BTHome.io standard",
"icon": "app.png", "icon": "app.png",
"tags": "bthome,bluetooth,temperature", "tags": "bthome,bluetooth,temperature",

51
modules/ble_advert.js Normal file
View File

@ -0,0 +1,51 @@
exports.set = function (id, advert, options) {
var _a, _b;
var bangle = Bangle;
if (Array.isArray(bangle.bleAdvert)) {
var found = false;
for (var _i = 0, _c = bangle.bleAdvert; _i < _c.length; _i++) {
var ad = _c[_i];
if (ad[id]) {
ad[id] = advert;
found = true;
break;
}
}
if (!found)
bangle.bleAdvert.push((_a = {}, _a[id] = advert, _a));
}
else if (bangle.bleAdvert) {
bangle.bleAdvert[id] = advert;
}
else {
bangle.bleAdvert = (_b = {},
_b[id] = advert,
_b);
}
NRF.setAdvertising(bangle.bleAdvert, options);
};
exports.remove = function (id, options) {
var bangle = Bangle;
if (Array.isArray(bangle.bleAdvert)) {
var i = 0;
for (var _i = 0, _a = bangle.bleAdvert; _i < _a.length; _i++) {
var ad = _a[_i];
if (ad[id]) {
delete ad[id];
var empty = true;
for (var _ in ad) {
empty = false;
break;
}
if (empty)
bangle.bleAdvert.splice(i, 1);
break;
}
i++;
}
}
else if (bangle.bleAdvert) {
delete bangle.bleAdvert[id];
}
NRF.setAdvertising(bangle.bleAdvert, options);
};

55
modules/ble_advert.ts Normal file
View File

@ -0,0 +1,55 @@
declare var exports: any;
type BleAdvert = { [key: string | number]: number[] };
type BangleWithAdvert = (typeof Bangle) & { bleAdvert?: BleAdvert | BleAdvert[]; };
type SetAdvertisingOptions = typeof NRF.setAdvertising extends (data: any, options: infer Opts) => any ? Opts : never;
exports.set = (id: string | number, advert: number[], options?: SetAdvertisingOptions) => {
const bangle = Bangle as BangleWithAdvert;
if(Array.isArray(bangle.bleAdvert)){
var found = false;
for(var ad of bangle.bleAdvert){
if(ad[id]){
ad[id] = advert;
found = true;
break;
}
}
if(!found)
bangle.bleAdvert.push({ [id]: advert });
}else if(bangle.bleAdvert){
bangle.bleAdvert[id] = advert;
}else{
bangle.bleAdvert = {
[id]: advert,
};
}
NRF.setAdvertising(bangle.bleAdvert, options);
};
exports.remove = (id: string | number, options?: SetAdvertisingOptions) => {
const bangle = Bangle as BangleWithAdvert;
if(Array.isArray(bangle.bleAdvert)){
var i = 0;
for(var ad of bangle.bleAdvert){
if(ad[id]){
delete ad[id];
var empty = true;
for(var _ in ad){
empty = false;
break;
}
if(empty) bangle.bleAdvert.splice(i, 1);
break;
}
i++;
}
}else if(bangle.bleAdvert){
delete bangle.bleAdvert[id];
}
NRF.setAdvertising(bangle.bleAdvert, options);
};

View File

@ -61,7 +61,7 @@
"*/*/*.ts", "*/*/*.ts",
"apps/*/*.js", // with checkJs: true "apps/*/*.js", // with checkJs: true
"*/*/*.d.ts", "*/*/*.d.ts",
"modules/*.d.ts", "modules/*.ts",
"typescript/types/*.d.ts" "typescript/types/*.d.ts"
] ]
} }