-
• #2
I have been trying to advertise as various things from the Puck, but the only things I can get to show up as being described properly in nRF are the examples, Temperature and Battery Life. I can't get blood pressure or environmental sensing to show up. I think you have to provide a byte array as data which has some required parameters for some services, but I don't know how to tell what data it needs or how to give it to it! The eddystone example works too, and that has a load of bytes in an array.
NRF.setAdvertising([0x03, // Length of Service List 0x03, // Param: Service List 0xAA, 0xFE, // Eddystone ID 0x13, // Length of Service Data 0x16, // Service Data 0xAA, 0xFE, // Eddystone ID 0x10, // Frame type: URL 0xF8, // Power 0x03, // https:// 'g','o','o','.','g','l','/','B','3','J','0','O','c'], {interval:100});
I don't really understand the gatt spec website either.
-
• #3
If I just do:
NRF.setAdvertising({ 0x180D: [ 99 ], 0x1809: [ 30 ], });
Then when I disconnect and re-scan in nRF connect I see:
Service Data: UUID: 0x180D Data: 0x63 Temperature: 30 C
And if I do:
NRF.setAdvertising({ 0x180F : [ 95 ], 0x1809: [ 30 ], });
I see:
Battery Level: 95% Temperature: 30 C
So Puck.js seems to be advertising everything just fine. Is it possible that the heart rate service isn't meant to be an advertisement, but is meant to be a service that you add with
NRF.setServices
?- Services: only available when you connect
- Advertisements: broadcast to the world when you're not connected
It seems more likely it's a service, since you maybe don't want to broadcast your heartrate to anyone that's listening?
You can always click
RAW
in nRF Connect and can see the complete advertising data if you want to compare your Pebble's advertising data with Puck.js.@gomako: I'm pretty sure that blood pressure will be a service, not advertising.
In
setAdvertising
if you supply a raw array, it just advertises that data - for the format you need to delve into the Bluetooth spec. Normally you'd supply an object though as I have above, and Puck.js creates that array for you automatically. - Services: only available when you connect
-
• #4
I've been reading through an older thread on BT on this forum and I've come to the same thought, that heart_rate should be a service not an advertisement.
I'm going to give that a try now. I took that route to start with, but didn't have much luck…that said, it was 18 hours ago, so maybe my brain has soaked up more of the GATT spec!
Will report back.
-
• #6
Quick update:
- Using
setService
doesn't blow away UART (I think this puck was just taking some time to pick up). - I've got a heart_rate advertising, but…it's not quite there.
Note that the value is totally wrong. I'm also trying to connect from a webpage, which doesn't discover that this device has heart_rate (I think it's filtering on the service), but baby steps!
- Using
-
• #7
You'll need to use the format of data that's specified here: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml
Looks a bit cryptic, so it might be easier to copy some data values from someone else's example code?
-
• #8
@Gordon yeah, I've been reading through the specs (and parsing existing data).
I know (hmm "know", not sure that's accurate!) that sending a value of
0x06
,0x2c
should send the right flags to say the heart_rate monitor is connected and the heart rate is 44bpm.I was thinking something like this:
NRF.setServices({ 0x180D: { // heart_rate 0x2A37: { // heart_rate_measurement broadcast: true, readable: true, notify: true, indicate: true, value : 0x2C06, } } })
Which does kinda work, but I also believe the device needs to advertise it has heart_rate services - which this doesn't seem to be doing, otherwise filtering for the service doesn't seem to work (or certainly the demo page I'm working from doesn't see it)
-
• #9
Oh, also note that I've tried sending the following - none really work:
value: 0x2C06
value: [0x06, 0x2C]
value: 0x062C
…which does suggest I'm basically making it up as I go along!
-
• #10
@Gordon I think I've found an adafruit example that I might be able to use as documentation, except I think I need to know where the bit flags for the
setServices
properties are set.For example, if I have
broadcast: true, notify: true
, where are those flags in C? What's the value of the GATT property? (I think…)I've been poking around the C files, but I'm not familiar with the code at all.
-
• #11
When you send
value : 0x2C06
, Espruino doesn't know it's supposed to be sending 16 bits - it just sends it as an 8 bit value.I think you probably want:
value : [0x2C, 0x06]
and that'll fix it.Those flags are for the characteristic itself (rather than the data) - I really don't think you need to delve that deeply - where's the adafruit example code?
-
• #13
Looking at this:
AT+GATTADDCHAR=UUID=0x2A37, PROPERTIES=0x10, MIN_LEN=2, MAX_LEN=3, VALUE=00-40
I'm not 100% sure how to represent the value
00-40
in a way that the puck will understand. Would I give it hex? Is this something else?I'm guessing that properties is one of the flags like
readable
,notify
, etc - but not sure which. Is this the same as[0x00, 0x40]
? Any ideas? -
• #14
I'm guessing that properties is one of the flags like readable, notify, etc - but not sure which.
I'm sure that'd be in Adafruit's docs somewhere? It's not something you should really try and figure out from Puck.js's source.
And yes, 00-40 sure sounds like it should be
[0x00, 0x40]
to me.That also fits with the spec I posted earlier. It'd mean:
- Heart Rate Value Format is set to UINT8. Units: beats per minute (bpm)
- Sensor Contact feature is not supported in the current connection
- Energy Expended field is not present
- RR-Interval values are not present.
And 0x40 is 64. So a heart rate of 64 BPM
- Heart Rate Value Format is set to UINT8. Units: beats per minute (bpm)
-
• #15
Quick update, I'm able to read heart rate of 40bpm (with contact detected) and body sensor location: wrist on nRF.
But it's not advertising (yet).
Here's the code (because I'm not tracking changes!):
NRF.setServices({ 0x180D: { // heart_rate 0x2A37: { // heart_rate_measurement notify: true, readable: true, broadcast: true, value : [0x06, 0x40], }, 0x2A38: { readable: true, value: [0x02] } } });
-
• #16
0x06
in the heart_rate_measurement is the flags and says that it's got contact.0x40
is the heart rate0x02
is the sensor location value
-
• #17
Quick update, I've got the
heart_rate
service advertising and "working". Note that I lifted thesetAdvertising
values from here and just copied theGAPSETADVDATA
value into a hex array, but I really don't understand why it works.var hr = 65; function update() { hr++; if (hr > 120) { hr = 65; } NRF.updateServices({ 0x180D: { // heart_rate 0x2A37: { // heart_rate_measurement notify: true, value : [0x06, hr], } } }); setTimeout(update, 1000); } NRF.setServices({ 0x180D: { // heart_rate 0x2A37: { // heart_rate_measurement notify: true, value : [0x06, hr], }, 0x2A38: { readable: true, value: [0x02] } } }); NRF.setAdvertising([ 0x02, 0x01, 0x06, 0x05, 0x02, 0x0d, 0x18, 0x0a, 0x18 ], { name: "puck heart", // this doesn't stick at all, no idea why showName: true, discoverable: true, interval: 600 }); // if I update too early, it seems like GATT is still trying to do the previous updates setTimeout(update, 2000);
-
• #18
Ahh, right. So you have 3 specific things:
- Advertising data - data that's broadcast to everyone
- Advertised services - broadcasting 'I can do X', but not containing data
- Actual services - data once connected
Unfortunately Puck.js doesn't let you define advertised services right now - but you managed to find a way around it by explicitly setting the raw advertising data, so it looks like you're sorted :)
I've filed a bug and I'll try and add the ability to set advertised services at some point in the future.
- Advertising data - data that's broadcast to everyone
-
• #19
One really weird thing I do see, is if I redeploy the code, the service no longer advertises correctly (it's like it completely resets).
I'm having to do a hard reset on the puck to get back to advertising.
-
• #20
You'd definitely have to disconnect and reconnect for it to take effect (since Espruino would think the services have changed and the only way to change the services on nRF52 is for Espruino to totally reset the Bluetooth stack, which it can only do when nothing is connected).
It might be that the automatic BLE reset means that the data set in
setAdvertising
gets lost.Can you try sticking
NRF.setAdvertising
insideupdate()
for now? If so I can see if I can change the software a bit so it remembers. -
• #21
Yeah, putting the
setAdvertising
in the update did seem to do the trick.Still a bit weird that the name isn't set, though I can see it on the nRF Connect app if I explicitly read the value, but my browser (via webBT) is still reading the old "Pluck 1234" value. Not a biggie though.
Now seeing if I can add some more services to this poor little puck!
-
• #22
Ok, thanks - I'll add that to my To Do list then.
You're not seeing the name because you're specifying raw BLE advertising data which doesn't have the name specified in it. If you added the right sequence of bytes to specify a name then you'd be able to do that as well.
My guess is anything that's still showing a name just has it cached.
-
• #23
Ok, this is now done and will be in 1v92. You can do:
NRF.setServices({ 0x180D: { // heart_rate 0x2A37: { // heart_rate_measurement notify: true, value : [0x06, hr], }, 0x2A38: { readable: true, value: [0x02] } } }, {advertise:[0x180D]});
to start advertising the heart rate service.
-
• #24
very cool, thanks! Looking forward to 1v92 for my puck :)
I'm trying to make a little game with the puck, and the first part of my plan is to advertise the puck as a heart_rate monitor (service: 0x180D).
When I check the puck after a deploy with the Android nRF Connect app, it doesn't list heart_rate as a service.
When I compare to my Pebble, I can see it explicitly listed under flags & services.
The odd thing is I can advertise as a temperature gauge - but it's entirely possible I'm making mistakes.
This is my code:
Temperate correctly shows as 30c (in nRF connect), but the heart_rate is missing.
Any ideas/help?
Thanks!