Reading BLE service in Appinventor

Because if the heart beats like metronome, you would be dead in 4 days. :wink:

"If the pattern of the heartbeat becomes regular as the tapping of woodpecker or the dripping of rain from the roof, the patient will be dead in four days." (Wang Shu-h, Chinese doctor, 3rd century AD)

This sentence can be found in almost every article / book on heart rate variability (HRV).

1 Like

Hello, I found this:

As an example, the Heart Rate Measurement characteristic is mandatory for the Heart Rate Service, and uses a UUID of 0x2A37. It starts with a single 8-bit value describing the HRM data format (whether the data is UINT8 or UINT16, etc.), and the goes on to include the heart rate measurement data that matches this config byte.

In an older BLE Heart Rate Project that I worked on in the middle of last year (hardly any memories of it), this was used:

Thank you @Anke, I started with that project but it was not capturing data.
The recommendation was that for the GATT service registration was better.

I was using this BLE device for heart beat measurement:


that worked fine for me. When I found it again :wink:, I’ll try to do another test with the new BLE ext.

I’m rather surprised by your report that using read/register for bytes returned nothing. The bytes representation is the most basic and essentially gives you access to the underlying packet without any interpretation of the values. Every other type requires some interpretation as each type is larger than 1 byte (other than bytes, of course).

I also want to point out that the heart rate service and heart rate measurement characteristic are a bit more sophisticated than just reading a value off the wire. In particular, the first byte of the packet is a bitfield containing flags that are used to interpret the remainder of the packet (Bluetooth SIG reference).

If we look at the underlying representation of your data, it will look like this (hex):

00 66
00 67
00 68
00 69
00 6A
...

The first byte is the flag byte, and the important bit here (pun intended) is that it indicates that there is only a single byte of data in the remainder of the packet. The second byte is the data byte. Your sketch mimics a heart rate monitor by simply counting from 100 to 175 and then resetting back to 100 ad infinitum and we can see that behavior exhibited here in your data.

When you attempt to interpret the data as short (16-bit) values, they are interpreted least-significant bit first, so the first value will be 0x6600, or 26112, the second will be 0x6700 (26368), etc. Likewise, with the interpretation as strings you end up seeing the ASCII interpretation of these values (f, g, h, …).

To facilitate working with this type of data, I’ve created the following extension:

It requires this version of the BLE extension and will not work with earlier versions of the extension:

And here is a test app that I used to test with an Arduino using a similar sketch to the one you showed above.

HeartRateTest.aia (196.5 KB)

2 Likes

Hello
The program works correctly @ewpatton, fantastic.
But this was only a first step of my work, if I want to use other GATT services, I think I could not with that library.
I have also thought to use the heart rate to send other types of data, but I see that it only reads values up to 250; Yes, I know that above 250 bpm we talk about impossible.

I have to think of other possibilities like UART. But I can't get it up and running on my max32630fthr.

Thank you very much once more for your help. You are great.

Yes, and I checked my BLE_HRM app with the new BLE ext.
Doesn't work, but worked fine with previous BLE version.

Could you expand on this?

This app works fine with the old BLE extension, but not with the new one.
BLE_HRM.aia (782.1 KB)

Maybe some of these blocks (with the new BLE ext) help:

and these are from your (working) HeartRateTest.aia:

I haven't worked on these BLE HeartRate apps for a long time, so I'm something out of the topic.

Hello again
Well, since I had to receive three data on the mobile, PPG (2 data) and ECG (1 data), I have not known how to use the GATT Service.
I have been recommended to do it through UART. I have managed to make a program that sends those three data. I receive them in a string of the form:
498, 496, 245,
I read them well from Serial Bluetooth Terminal, and in nRF Connect I see this:

I have seen many examples, of applications in App Inventor, to read this data on mobile. But there is a lot of information.
Can you help me choose a good example for this please?

With the UART the program from before works perfectly:

Now I need to separate the three data to process them separately. Any help please?

Hello again
The latter is also fixed. I put it here in case someone helps:

@ Anibal_de_la_Torre Did you use the new BLE and Heart-Rate extensions? Did you use "shorts" as data type? Would you mind posting the final "aia" file for your last two posts?

hi there @ABG - sorry I'm late responding, I've just posted some hopefully useful stuff here - I got involved with decoding live data from a Stryd power meter and a Polar heart rate monitor - the project got massive and since I got a running watch not looked at the code for months and months now. Anyway have a look at this and see if it helps : BLE GATT characteristic parsing
Cheers,
Martin

Hurrah, success. It's interesting to see that I can now follow a lot of the previous posts and the code now I've been through the loop myself.

There were lots of concepts I had to discover and figure out in going from BLE noob to getting it working.

First was trying to hack old programs was a real struggle as they didn't work. Watch out for lack of backwards compatibility with old code and the bluetooth extension. I got all sorts of weird errors about advertisements and failures that I couldn't figure out - old extensions.

Second was in trying to understand how bluetooth LE works. The basic are quite straightforward - once you know!!!

Essentially you have to start scanning for BT devices

component_method

Then you have an event handler for whatever it finds. Stick whatever it finds into a listpicker (or another suitable ui element) - a list is returned (that was a gotcha!)

Then select a device from the list. - You have to display the list of course (well it's of course now I figured it out!)

blocks (3)

![blocks

Okay now that you have a device (and don't forget that it may take a few moments for all sensors/devices to be recognised, then you can start interrogating the sensor (in my case a Garmin chest heart rate monitor)

You need two magic numbers aka
The service UUID


and the Characteristic UUID

These are used to get the data for the device.
Those numbers should work, but using a bluetooth sniffer such as nRF Connect from the Play Store (or similar e.g. BLE UUID Explorer or BLE Checker will be useful). There is an xml spec at bluetooth.com - heart rate service xml which may provide some help.

So from code, we now need to respond to the connected event and register a callback (event listener) for any data and also to enable reading the data

1 Like

Oh how annoying and frustrating that I cannot post more images or create more replies - you really don't help do you.

I've shown in these blocks how to get the information on what services and characteristics the sensor supports - but lot of info is sent so I used a text box to show it.

So there is the register a service and the readShorts - and that was another gotcha. You'd have thought it would send an integer value. But no, it sends a short (2 byte value 16 bits) (and it's unsigned because it's not a positive or negative number) and the big gotcha is that this data is in a list object and that the index for a list object starts at 1, not zero like just about every other programming language I've used (apart from dear old BASIC). It seems to me that getting just the first element will do the job - but I maybe wrong, I couldn't see any other elements in the list when I debugged it.

Anyway, when you've done these steps then you need an actual listener to respond to the data that is sent (arbitrarily/asynchronously?) from the sensor.

So what is the format of this short:

Well if I just output the short to a label I was getting a number like 23312 and similar.

In binary this is

0 1 0 1 1 0 1 1 0 0 0 1 0 0 0 0

Split this into a most significant byte and a least significant byte
0 1 0 1 1 0 1 1 and 0 0 0 1 0 0 0 0

Now look at the least significant bit at the far right. If this is a 0 then the heart rate is in the most significant byte (8 bits) and if a 1 then the data is 16 bits (and I don't know what you look at!

So 0 1 0 1 1 0 1 1 is 91 in decimal - a bit fast, but I was excited!!!

How get that most significant byte? In assembly language and up you would shift the short 2 bytes to the right by 8 bits, which is the same as dividing by 256 and losing any fraction - hence the format to 0 decimal places.

Anyhow the main code looks like the following and hacked from some code by Jose Luis Núñez (I think his app is on the Play Store but needs the newest BLE extension and some refactoring. It's also somewhere else as an aia but I can't remember where.)

Anyhow I hope this helps others who are taking their first steps. It took me four days of effort to get to this and it was really frustrating. But now it's done and I can move on to my speed and cadence sensors.

HeartRateMonitorGM.aia (314.5 KB)

1 Like

could you provide the app ?

Gordon - thank you for the code and explanations. I started playing with it, and it works fine when run in companion mode, but when I create an .apk and install it, the BLE scanning does not see any devices. Is this a known issue? Thanks for any insights. Dino