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/widbtstates/
apps/widhid/
modules/ble_advert.js

View File

@ -1,2 +1,3 @@
0.01: Initial release.
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() {
if(Array.isArray(Bangle.bleAdvert)){
// 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()];
require("ble_advert").set(0x180F, [E.getBattery()]);
}
NRF.setAdvertising(Bangle.bleAdvert);
}
if (!Bangle.bleAdvert) Bangle.bleAdvert = {};
setInterval(advertiseBattery, 60 * 1000);
advertiseBattery();
})();

View File

@ -2,7 +2,7 @@
"id": "bootgattbat",
"name": "BLE GATT 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",
"icon": "bluetooth.png",
"type": "bootloader",

View File

@ -1,3 +1,4 @@
0.01: Initial release.
0.02: Added compatibility to OpenTracks and added HRM Location
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.
*/
NRF.setAdvertising(
{
0x180d: undefined
},
{
require("ble_advert").set(0x180d, undefined, {
// We need custom Advertisement settings for Apps like OpenTracks
connectable: true,
discoverable: true,
scannable: true,
whenConnected: true,
}
);
});
NRF.setServices({
0x180D: { // heart_rate
@ -28,7 +23,6 @@
}
}
});
}
const keepConnected = (require("Storage").readJSON("gatthrm.settings.json", 1) || {}).keepConnected;

View File

@ -2,7 +2,7 @@
"id": "bootgatthrm",
"name": "BLE GATT 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",
"icon": "bluetooth.png",
"type": "bootloader",

View File

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

View File

@ -3,3 +3,4 @@
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)
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 = [];
{
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();
var advert = require("BTHome").getAdvertisement(Bangle.btHomeData)[0xFCD2];
// 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 updateTimeout = 10*60*1000; // update every 10 minutes
if (options.event) { // if it's an event...
@ -60,7 +44,7 @@ Bangle.btHome = function(extras, options) {
advOptions.whenConnected = true;
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);
Bangle.btHomeTimeout = setTimeout(function() {
delete Bangle.btHomeTimeout;

View File

@ -1,7 +1,7 @@
{ "id": "bthome",
"name": "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",
"icon": "icon.png",
"type": "app",

View File

@ -1,2 +1,3 @@
0.01: New App!
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
];
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;
}
NRF.setAdvertising(Bangle.bleAdvert);
require("ble_advert").set(0xFCD2, advert);
}
// 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);});
}
if (!Bangle.bleAdvert) Bangle.bleAdvert = {};
setInterval(function() {
drawTemperature();
}, 10000); // update every 10s

View File

@ -1,7 +1,7 @@
{ "id": "bthometemp",
"name": "BTHome Temperature and Pressure",
"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",
"icon": "app.png",
"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",
"apps/*/*.js", // with checkJs: true
"*/*/*.d.ts",
"modules/*.d.ts",
"modules/*.ts",
"typescript/types/*.d.ts"
]
}