zacharyedwardbull / pycycling

A Python package for interacting with Bluetooth Low Energy (BLE) compatible bike trainers, power meters, radars and heart rate monitors
https://pypi.org/project/pycycling/
MIT License
131 stars 25 forks source link

Support for Bluetooth CYCLING POWER FEATURE Characteristic #5

Closed ElreboCM closed 3 years ago

ElreboCM commented 3 years ago

It would be really cool if you could support the Cycling Power Feature Characteristic as well.

zacharyedwardbull commented 3 years ago

Hey, many thanks for creating this issue.

I'm pretty sure we already support the cycling power feature. Try using the get_cycling_power_feature() method.

Implementation at: https://github.com/zacharyedwardbull/pycycling/blob/8cba37b28432be9d76bf5a4092f0ce453b773919/pycycling/cycling_power_service.py#L113

Let me know how you get on, Zachary

ElreboCM commented 3 years ago

Hi. Yes your are right. I will have a closer look. I am testing it with a SRAM QUARQ AXS.

zacharyedwardbull commented 3 years ago

Did you manage to get pycycling to work with the SRAM QUARQ AXS in the end? Cheers

ElreboCM commented 3 years ago

The Power Measurement Characteristic works fine. The fact that instantaneous power is 0 is because I am spinning the crank by hand and the bike is on a stand.

image

However I do not get an out put for the Power Vector Characteristic (I name it incorrectly for the issue) does not have an output. Where do you print the output? I could not find it in your code...

import asyncio
from bleak import BleakClient

from pycycling.cycling_power_service import CyclingPowerService

async def run(address):
    async with BleakClient(address) as client:
        def my_measurement_handler(data):
            print(data)
        await client.is_connected()
        trainer = CyclingPowerService(client)
        trainer.set_cycling_power_measurement_handler(my_measurement_handler)
        #await trainer.enable_cycling_power_measurement_notifications()
        await trainer.enable_cycling_power_vector_notifications()
        await asyncio.sleep(30.0)
if __name__ == "__main__":
    import os
    os.environ["PYTHONASYNCIODEBUG"] = str(1)
    device_address = "08894FCF-5A2A-4468-78C1-A9871E2F4154"
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run(device_address))

in your example you are twice subscribing to the Power Measurement Characteristic. I guess that is a mistake? At least I got an error that I am already subscribed to that characteristic.

ElreboCM commented 3 years ago

Ah looks like I forgot to set the power vector handler properly. I Will try again when I find some time.

ElreboCM commented 3 years ago
image

That appears to be working ๐Ÿ‘

A while ago also tested a Sigeyi AXO. That one was working too!

zacharyedwardbull commented 3 years ago

Glad you managed to get it to work!

Improving the documentation is the top of my priority list for this package, hopefully I'll have a chance to do that sometime this summer.

ElreboCM commented 3 years ago

It is actually quite straightforward to use if you look closely at the code. Nonetheless a bit more documentation wonโ€™t harm.

The only thing that is missing for full cycling power service support is the extreme angles field in the power management characteristic?

ElreboCM commented 3 years ago

One thing that strikes me however:

If you look at the torque magnitude array you can spot values above 65000. This field is a signed int. Could it be that you are not taking the sign into account when doing the conversion from byte?

ElreboCM commented 3 years ago

Changed the code in the power vector handler to convert the intantenous force / torque to signed int

            element = int.from_bytes(data[i:i + 2], 'little', signed="true")

Looking good now ๐Ÿ˜€

image
zacharyedwardbull commented 3 years ago

Looks like you found a bug! I'll fix this as you have done when I have a free moment. Thanks for finding it and posting a fix.