polarofficial / polar-ble-sdk

Repository includes SDK and code examples. More info https://polar.com/en/developers
Other
449 stars 147 forks source link

PMD Control Point responses #360

Closed stuartlynne closed 9 months ago

stuartlynne commented 1 year ago

I am working with the Polar H10 using Python Bleak.

I am able to get both ECG and ACC streaming, but would like to clarify what I should be seeing as responses to requests on the PMD Control point.

Here is a summary of write requests and responses.

write Request ECG Stream Settings 01 00 
read  Request ECG Stream Settings 0f 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
write Request ACC Stream Settings 01 02 
read  Request ACC Stream Settings 0f 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
write Start ECG Stream 02 00 00 01 04 01 01 01 0e 00 
read  Start ECG Stream 0f 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
write Start ACC Stream 02 02 02 01 08 00 00 01 c8 00 01 01 10 00 
read  Start ACC Stream 0f 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

While the H10 responds correctly to the requests (i.e. starts streaming ECG and ACC) the response to all requests is always:

0f 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

I don't get the responses shown in the Polar_Measurement_Data_Specification.pdf.

Modiug commented 1 year ago

I see the same behavior when using att_read = await client.read_gatt_char(PMD_CONTROL) to read the response after a client.write_gatt_char(). You can get the right response by enabling notification, e.g.: await client.start_notify(PMD_CONTROL, pmd_control_notification).

But I also do not know why it behaves like this.

Additionally, I have the issue that I can start a stream only once (OH1 in my case). Running my Python/Bleak script again will show all the correct resposes, but no streaming data is sent. It only works again, after rebooting my machine. But again only once.

stuartlynne commented 1 year ago

Thanks for your feedback. My first test with that start_notify instead of a read appears to work.

I am testing with a PolarH10 and normally can start and stop streams without trouble.

stuartlynne commented 1 year ago

If you have a short version of your script you can share, I can test it here against the Polar H10 to see if I see the same issue WRT to starting streams a second time.

Modiug commented 1 year ago

I actually have an OH1 and an H10. When stopping the stream before exiting, I am partially successful on the OH1, but the H10 still only streams ACC data once after reboot. The following script shall be able to demonstrate the issue. It works for OH1 and H10 as the ACC settings are valid for both devices. When I run it a second time, I just get:

Get ACC Settings
pmd_control_notification():
 f0 01 02 00 00 00 04 19 00 32 00 64 00 c8 00 01 01 10 00 02 03 02 00 04 00 08 00
Start ACC measurement
pmd_control_notification():
 f0 02 02 00 00 01
Stop ACC measurement
pmd_control_notification():
 f0 03 02 00 00
DONE

Please give it a try. Maybe I missed something.

#!/usr/bin/env python3

import asyncio
from bleak import BleakClient

PMD_CONTROL = "FB005C81-02E7-F387-1CAD-8ACD2D8DF0C8"
PMD_DATA = "FB005C82-02E7-F387-1CAD-8ACD2D8DF0C8"

## PMD commands
ACC_START_MEASUREMENT = bytearray([
    # theses setting shall work work OH1 and H10
    0x02, 0x02,             # Start measurement ACC
    0x00, 0x01, 0x32, 0x00, # Set sample rate 50sps
    0x01, 0x01, 0x10, 0x00, # Set resolutions 16
    0x02, 0x01, 0x08, 0x00, # Set range 8G
])

ACC_STOP_MEASUREMENT = bytearray([
    0x03, 0x02              # Stop measurement ACC
])

ACC_GET_SETTINGS = bytearray([
    0x01, 0x02,             # Get settings ACC
])

def pmd_control_notification(sender, data):
    print("pmd_control_notification():")
    print("".join([" %02x" %d for d in data]))

def pmd_data_notification(sender, data):
    print("pmd_data_notification():")
    print("".join([" %02x" %d for d in data]))

async def main(address):
    async with BleakClient(address) as client:
        # Start PMD_CONTROL and PMD_DATA notifications
        await client.start_notify(PMD_CONTROL, pmd_control_notification)
        await client.start_notify(PMD_DATA, pmd_data_notification)

        print("Get ACC Settings")
        await client.write_gatt_char(PMD_CONTROL, ACC_GET_SETTINGS)
        await asyncio.sleep(1.0)

        print("Start ACC measurement")
        await client.write_gatt_char(PMD_CONTROL, ACC_START_MEASUREMENT)  

        # Sleep a few seconds while streaming data comes in
        await asyncio.sleep(10)

        print("Stop ACC measurement")
        await client.write_gatt_char(PMD_CONTROL, ACC_STOP_MEASUREMENT)  

        # Stop notifications
        await client.stop_notify(PMD_DATA)
        await client.stop_notify(PMD_CONTROL)

if __name__ == "__main__":
    #asyncio.run(main("A0:9E:1A:C4:ED:97"))  # OH1
    asyncio.run(main("D4:FF:D9:5A:B6:16"))  # H10
    print("DONE")
stuartlynne commented 1 year ago

Are you testing in Linux and/or Windows?

I have to get a release of my software out today, hope to look at this tomorrow.

I have successfully pulled ECG out reasonably reliably, starting and stopping within the app and rerunning the app. My current app can grab either ECG or ACC or both starting and stopping either independently.

The typical hiccups are:

On Fri, Jun 23, 2023 at 3:36 AM Guido Muesch @.***> wrote:

I actually have an OH1 and an H10. When stopping the stream before exiting, I am partially successful on the OH1, but the H10 still only streams ACC data once after reboot. The following script shall be able to demonstrate the issue. It works for OH1 and H10 as the ACC settings are valid for both devices. When I run it a second time, I just get:

Get ACC Settings pmd_control_notification(): f0 01 02 00 00 00 04 19 00 32 00 64 00 c8 00 01 01 10 00 02 03 02 00 04 00 08 00 Start ACC measurement pmd_control_notification(): f0 02 02 00 00 01 Stop ACC measurement pmd_control_notification(): f0 03 02 00 00 DONE

Please give it a try. Maybe I missed something.

!/usr/bin/env python3

import asyncio from bleak import BleakClient

PMD_CONTROL = "FB005C81-02E7-F387-1CAD-8ACD2D8DF0C8" PMD_DATA = "FB005C82-02E7-F387-1CAD-8ACD2D8DF0C8"

PMD commands

ACC_START_MEASUREMENT = bytearray([

theses setting shall work work OH1 and H10

0x02, 0x02,             # Start measurement ACC
0x00, 0x01, 0x32, 0x00, # Set sample rate 50sps
0x01, 0x01, 0x10, 0x00, # Set resolutions 16
0x02, 0x01, 0x08, 0x00, # Set range 8G

])

ACC_STOP_MEASUREMENT = bytearray([ 0x03, 0x02 # Stop measurement ACC ])

ACC_GET_SETTINGS = bytearray([ 0x01, 0x02, # Get settings ACC ])

def pmd_control_notification(sender, data): print("pmd_control_notification():") print("".join([" %02x" %d for d in data]))

def pmd_data_notification(sender, data): print("pmd_data_notification():") print("".join([" %02x" %d for d in data]))

async def main(address): async with BleakClient(address) as client:

Start PMD_CONTROL and PMD_DATA notifications

    await client.start_notify(PMD_CONTROL, pmd_control_notification)
    await client.start_notify(PMD_DATA, pmd_data_notification)

    print("Get ACC Settings")
    await client.write_gatt_char(PMD_CONTROL, ACC_GET_SETTINGS)
    await asyncio.sleep(1.0)

    print("Start ACC measurement")
    await client.write_gatt_char(PMD_CONTROL, ACC_START_MEASUREMENT)

    # Sleep a few seconds while streaming data comes in
    await asyncio.sleep(10)

    print("Stop ACC measurement")
    await client.write_gatt_char(PMD_CONTROL, ACC_STOP_MEASUREMENT)

    # Stop notifications
    await client.stop_notify(PMD_DATA)
    await client.stop_notify(PMD_CONTROL)

if name == "main":

asyncio.run(main("A0:9E:1A:C4:ED:97")) # OH1

asyncio.run(main("D4:FF:D9:5A:B6:16"))  # H10
print("DONE")

— Reply to this email directly, view it on GitHub https://github.com/polarofficial/polar-ble-sdk/issues/360#issuecomment-1604087368, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACIUWJDYMKAZKBM2QYKBC3XMVWUFANCNFSM6AAAAAAWWY32MY . You are receiving this because you authored the thread.Message ID: @.***>

-- __O____ -\<,____ ____()/()___


@.***>__604-518-1749(m)604-461-7532(h)

Modiug commented 1 year ago

Thanks for looking into it. I am using Linux. The final use case is having a Raspberry Pi connecting to the sensors, but for now I am using my laptop for experimenting.

So, do I need to do something additional to make sure that BleakClient closes the BLE connection?

Multi-connect could be an issue, but I thought I switched it on. Maybe not on both devices. I am not sure what the blueman-applet from Linux does in the background, because sometimes a notification pops up showing the battery state. So, that could be interfering somehow.

Thanks for the pointers and good luck on your release.

jimmyzumthurm commented 9 months ago

Hi @stuartlynne , sorry for the late answer to your issue. It seems that you were reading the control point characteristic, which always returns the same thing which is normal. It is used to ask the devices which measurement types it supports. In that case, 0f 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -> second byte is the list of available features expressed as a bit vector -> 0000 1001 -> it means that ACC and ECG streams are supported (ACC = 2 -> bit2 =1, ECG = 0, bit0 = 1). Other 00 bytes are reserved for future use.

The response to writes on the control point characteristics are answered with BLE indications, so you would need to listen to these instead to get the settings and know if the start measurement was successful.

We are aware that we could put back updated technical specification to help developers who might want to implement the SDK functionality on other platforms / language, hopefully that can be done in the near future. Unfortunately don't have resources to directly support porting to other platforms, original goal of this SDK is to be used on Android/iOS and we support people that issues with that. As I see on this ticket, it seems sometimes non-Polar people help others quite a bit , which is really appreciated and nice to see ! For now I will close this ticket, please tell me if you still need help with that.

stuartlynne commented 9 months ago

I have a fairly extensive Python/Bleak test program showing how to access Polar via Bluetooth here: https://github.com/stuartlynne/pypolartest

Tested against H10 and OH1, probably would work with Verity as well.

On Tue, Sep 12, 2023 at 6:02 AM Jimmy Zumthurm @.***> wrote:

Hi @stuartlynne https://github.com/stuartlynne , sorry for the late answer to your issue. It seems that you were reading the control point characteristic, which always returns the same thing which is normal. It is used to ask the devices which measurement types it supports. In that case, 0f 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -> second byte is the list of available features expressed as a bit vector -> 0000 1001 -> it means that ACC and ECG streams are supported (ACC = 2 -> bit2 =1, ECG = 0, bit0 = 1).

The response to writes on the control point characteristics are answered with BLE indications, so you would need to listen to these instead to get the settings and know if the start measurement was successful.

We are aware that we could put back updated technical specification to help developers who might want to implement the SDK functionality on other platforms / language, hopefully that can be done in the near future. Unfortunately don't have resources to directly support porting to other platforms, original goal of this SDK is to be used on Android/iOS and we support people that issues with that. As I see on this ticket, it seems sometimes non-Polar people help others quite a bit , which is really appreciated and nice to see ! For now I will close this ticket, please tell me if you still need help with that.

— Reply to this email directly, view it on GitHub https://github.com/polarofficial/polar-ble-sdk/issues/360#issuecomment-1715682997, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACIUWO4IQE5SMXBV56IUDDX2BMM7ANCNFSM6AAAAAAWWY32MY . You are receiving this because you were mentioned.Message ID: @.***>

-- __O____ -\<,____ ____()/()___


@.***>__604-518-1749(m)604-461-7532(h)

jimmyzumthurm commented 9 months ago

Hi @stuartlynne , thank you very much for sharing your program and great job for getting it to work !