-
• #2
I just tried to run
NRF.setAdvertising({ 0x180D : [100, 80] }, { discoverable: true, connectable: true, scannable: true, whenConnected: true, interval: 600 });
on 52840 dongle with recent 2.17 build and it simply works, I see
Service Data 0x180d Data:0x6450
in nrfconnect on android near the device name in scan list and also see values in the "RAW" popup.
It even works when already connected to the device due towhenConnected: true
, device is still advertising.As for the setServices, that worked too
NRF.setServices({ '180d': { // Heart Rate Service UUID '2a37': { // Heart Rate Measurement Characteristic UUID value: [0x00, 0x00], // Initial value: HRM not available broadcast: false, readable: true, notify: true, description: "Heart Rate Measurement" } } });
I just tried it without and also with the
, { advertise: ['180d'] }
part and both work for me.
With the part in I see 0x180d both in service uuids and stil also as as direct servicee data as before.When connecting via nrfconnect I see "Heart Rate" service and can read the value of 0 bpm
-
• #3
And BTW the "more precise way" is something completely different, you can have one or the other or both but they are unrelated, it is not 'more precise' way.
-
• #4
Hey there I got your example working using following code:
NRF.setServices({ 0x180D: { // heart_rate 0x2A37: { // heart_rate_measurement notify: true, value : [0x06, 0], } } }, { advertise: [ '180D' ] }); Bangle.setHRMPower(1); Bangle.on('HRM', function(hrm) { NRF.updateServices({ '180d': { '2a37': { value: [0x06, hrm.bpm], notify: true } } }); });
With this code, I could see the heart rate inside the nRF connect app as well as in FitoTrack for Android. However, I got two problems to solve: First, setServices requires a BLE restart. Secondly, if the device is already connected to e.g. gadgetbridge it is not discoverable except when I trigger it within the bluetooth settings.
-
• #5
@user155613 Thank you for your feedback and signalling potential problems!
-
• #7
Glad it's sorted! The BLE restart happens automatically if the Bangle is not connected, or as soon as the Bangle becomes disconnected - which I guess should happen in most cases anyway.
On Bangle.js 2v18 firmware you can actually use Advertising and request it to keep advertising even while the Bangle is connected, so that could be an option - but Web Bluetooth's handling of scanning for Advertising isn't available on as many platforms as Web Bluetooth connections .
-
• #8
On Bangle.js 2v18 firmware you can actually use Advertising and request it to keep advertising even while the Bangle is connected, so that could be an option - but Web Bluetooth's handling of scanning for Advertising isn't available on as many platforms as Web Bluetooth connections .
Does this mean that calling setAdvertising would suffice on 2v18?
Can I advertise complex objects the same way i would using setServices? -
• #9
You need to call http://www.espruino.com/Reference#l_NRF_setAdvertising with
whenConnected:true
I'm not entirely sure what you mean about complex objects - you can advertise multiple services, but there is only so much space available in the packet (it's ~20 bytes).
-
• #10
Sorry for the confusion! I want to advertise this object in order to comply to the standard:
0x180D: { // heart_rate 0x2A37: { // heart_rate_measurement value : [0x06, 0], } }
-
• #11
I want to advertise this object in order to comply to the standard:
which standard? GATT Heart Rate Service documented here
https://www.bluetooth.com/specifications/specs/heart-rate-profile-1-0/
is different from just advertising the data. Just went briefly through HRP_V10.pdf and don't see that you should advertise it "to comply to the standard"You are mixing two relatively unrelated BLE features. Advertising is GAP. Services/characteristics is GATT. GATT works over connections, advertising does not.
-
• #12
Yes, unfortunately you can't do that and have it magically work with apps that are expecting the HRM Service on a connection. What you can do is advertise
0x2A37 : [0x06, 0]
and it's possible that an app likeNRF Connect
might pick it up, but it's not the same as the HRM spec and it won't work with apps unless they are designed for it. -
• #13
@AnotherStranger @Gordon Sorry to bother you again but the issue pointed out by AnotherStranger is actually not allowing me to properly develop an app. The following code, even though makes the heart rate service available, throws this error in the IDE:
function onInit() { Bangle.setHRMPower(1); NRF.setServices({ '180d': { // Heart Rate Service UUID '2a37': { // Heart Rate Measurement Characteristic UUID value: [0x00, 0x00], // Initial value: HRM not available broadcast: false, readable: true, notify: true, description: "Heart Rate Measurement" } } }, { advertise: ['180d'] }); Bangle.on('HRM', function(hrm) { NRF.updateServices({ '180d': { '2a37': { value: [hrm.confidence, hrm.bpm], notify: true } } }); }); } onInit();
Trying to resolve the issue with the need for restart does not seem to resolve the problem. I have tried this:
function onInit() { Bangle.setHRMPower(1); NRF.setServices({ '180d': { // Heart Rate Service UUID '2a37': { // Heart Rate Measurement Characteristic UUID value: [0x00, 0x00], // Initial value: HRM not available notify: true, description: "Heart Rate Measurement" } } }, { advertise: ['180d'] }); Bangle.on('HRM', function(hrm) { NRF.updateServices({ '180d': { '2a37': { value: [hrm.confidence, hrm.bpm], notify: true } } }); }); } // Restart Bangle.js to apply the updated advertising Bangle.on('kill', function() { NRF.setAdvertising({}); // Stop advertising load(); // Restart Bangle.js }); onInit();
I have also tried this (introducing a timeout):
function onInit() { Bangle.setHRMPower(1); NRF.setServices({ '180d': { // Heart Rate Service UUID '2a37': { // Heart Rate Measurement Characteristic UUID value: [0x00, 0x00], // Initial value: HRM not available broadcast: false, readable: true, notify: true, description: "Heart Rate Measurement" } } }, { advertise: ['180d'] }); Bangle.on('HRM', function(hrm) { setTimeout(function() { NRF.updateServices({ '180d': { '2a37': { value: [hrm.confidence, hrm.bpm], notify: true } } }); }, 500); // Delay in milliseconds before updating services }); } onInit();
This code still resulted in an error:
in function called from system
Uncaught Error: Can't update services until BLE restart
at line 1 col 79
...idence,hrm.bpm],notify:true}}});Is there an established way to do this that I've missed perhaps? Thank you in advance!
-
• #14
Uncaught Error: Can't update services until BLE restart
You need to disconnect everything including the IDE from the device to let the BLE stack restart automatically, then it will start working. You can wrap the update in try catch block if the exception breaks something.
-
• #15
Thanks everyone! The problem of the app not continuously advertising the data when deployed as an app and not via Espruino IDE was actually the fact that the program would quit before advertising anything. So I needed to implement a keep alive function. The app is functioning now. Thank you!
-
• #16
Hi, maybe just try:
Bangle.setHRMPower(1); NRF.setServices({ '180d': { // Heart Rate Service UUID '2a37': { // Heart Rate Measurement Characteristic UUID value: [0x00, 0x00], // Initial value: HRM not available broadcast: false, readable: true, notify: true, description: "Heart Rate Measurement" } } }, { advertise: ['180d'] }); Bangle.on('HRM', function(hrm) { try { NRF.updateServices({ '180d': { '2a37': { value: [hrm.confidence, hrm.bpm], notify: true } } }); } catch (e) { NRF.disconnect(); } });
No need for the
onInit
stuff.You'll need to connect to the Bangle after you run the app. The
NRF.disconnect()
in the try...catch will force the Bangle to disconnect if you'd forgotten to disconnect before (if the services hadn't updated) and then you'll have to reconnect -
• #17
@Gordon Thanks for pointing this out - moving the code outside the init() function does not require setInterval to keep the program alive, as it is done directly by HRM events. Thank you! Just wanted to as you one last thing - for now the app only runs when it is open - as soon as I get back to the main menu, the advertising stops. Is this an intended way to do it or is there a way to run it in the background? I've tried playing with
g.clear(); Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets();
but it recreates the main screen in an arbitrary way. As soon as I want to interact with the menu (press the side button), the program stops.
-
• #18
Yes, that's the intended behaviour - basically because code is of varying quality, if we left all apps in charge of cleaning themselves up, many wouldn't and Bangle.js would be very unreliable after a while.
So what we do is when loading a new app we tear everything down, and restart it. Some apps like some clock/launchers implement 'fast load' which lets them swap between themselves quickly without that full load but on the whole when launching apps everything gets removed.
You can add 'boot code' (a file called
myapp.boot.js
) which always runs every time you switch apps, so you can put your code in there - I assume this is you actually? https://github.com/espruino/BangleApps/pull/2802So I probably already answered this when it was asked in the PR too :)
Hi, I'm struggling with an issue and would really appreciate any help! I'm trying to implement a simple web application that connects to my Bangle.js 2 and visualises the received heart rate data. I would like to advertise heart rate service as as GATT service following all the specifications. I've tried many many versions of the code below (loading it via Espruino IDE for now) but nothing seems to work.. None of the services can be found when using nrFConnect and LightBlue. I've tried both NRF.setAdvertising like so (simplified version):
I've also tried a more precise way using NRF set and update services:
However, when I send my heart rate data using UART (following this tutorial here: http://www.espruino.com/Bangle.js+Data+Streaming#bonus-2-heart-rate-monitoring-graph), it works correctly and I'm able to receive this data on my web app:
I would really appreciate any help regarding this as I'm new to Espruino and Bluetooth in general and struggling to find a solution. Just a quick note: my web app is currently not scanning for the services but I would assume that if advertising works correctly, it should come up on nRFConnect and LightBlue.
Thanks for your help in advance!