peplin / pygatt

Python wrapper for gatttool (a deprecated tool from BlueZ) and the BGAPI for accessing Bluetooth LE Devices
Other
527 stars 185 forks source link

multiple subscriptions slows down characteristic throughput #197

Closed chrishunt93 closed 3 years ago

chrishunt93 commented 6 years ago

TLDR: Does anyone have an idea how to subscribe to multiple notifications using PyGATT without significant packet loss?

I have been having an issue with some BLE interfacing code for some while now. I am using the PyGATT module in Python 3 on a Linux machine to receive data from a Bluetooth LE device (MyoArmband from Thalmic Labs). For some reason, I am not able to get the advertised sampling rate for any of the data streams (EMG and IMU). I can connect and set up the device fine, however, my computed sampling rates are much slower than they should be.

For example, I should be getting a data rate of 200 Hz for EMG and 50 Hz for IMU, however, with this code I am only getting ~70 Hz from EMG and ~17 Hz IMU. I've tested a few configurations and determined that if I only subscribe to a single characteristic at a time, I can get the correct sampling rate for that characteristic. This suggests that my code must be dropping packets only when multiple characteristics are subscribed to. Is this a known issue with PyGATT / is there any way around this? If not with PyGATT, does anyone have a suggestion for another module that I can use in Python for interfacing with BLE devices (preferably cross-platform)?

Note: I've attached my code for reference.

import pygatt
import time
import numpy as np

emgcount = 0
imucount = 0

def emg_handler(handle, value): 
    global emgcount 
    emgcount += 2

def imu_handler(handle, value): 
    global imucount 
    imucount += 1

def main():
   btle = pygatt.BGAPIBackend()

    btle.start()
    myo = btle.connect( 'e0:f2:99:e7:60:40' )

    try:
        # set parameters
        myo.char_write('d5060401-a904-deb9-4748-2c7f4a124842', b'\x01\x03\x00\x00\x00')   # deregister all streaming
        myo.char_write('d5060401-a904-deb9-4748-2c7f4a124842', b'\x0a\x01\x02')           # lock myo
        myo.char_write('d5060401-a904-deb9-4748-2c7f4a124842', b'\x09\x01\x01')           # don't sleep
        myo.char_write('d5060401-a904-deb9-4748-2c7f4a124842', b'\x01\x03\x02\x01\x00')   # stream filtered emg and imu

        # subscribe to everything
        myo.subscribe('d5060402-a904-deb9-4748-2c7f4a124842', callback = imu_handler)
        myo.subscribe('d5060105-a904-deb9-4748-2c7f4a124842', callback = emg_handler)
        myo.subscribe('d5060205-a904-deb9-4748-2c7f4a124842', callback = emg_handler)
        myo.subscribe('d5060305-a904-deb9-4748-2c7f4a124842', callback = emg_handler)
        myo.subscribe('d5060405-a904-deb9-4748-2c7f4a124842', callback = emg_handler)

        print( 'Streaming...' )
        t0 = time.time()
        while ( time.time() - t0 ) < 10.0: 
            time.sleep( 1.0 )

    finally:
        tf = time.time()
        btle.stop()

        print('')
        print( 'EMG SAMPLING RATE:', emgcount / ( tf - t0 ) ) # should be ~200, is returning ~70
        print( 'IMU SAMPLING RATE:', imucount / ( tf - t0 ) ) # should be ~50, is returning ~17

if __name__ == '__main__':
    main()
bem22 commented 4 years ago

I have the exact problem when trying to acquire data from 3 characteristics from multiple BLE devices. I believe it's because of the threading mechanism behind the adapters, that is trying to acquire the hci interface. I have subscribed successfully to characteristics that almost reach the maximum BLE bandwidth, however, when having multiple devices at the same time, the communication is badly slowed down.

peplin commented 3 years ago

I expect the two backends (GATTTool and BGAPI) to have very different performance. The former is (yuck) parsing string output from the gatttool CLI and I wouldn't be surprised if the performance isn't very good. This is the backend using hci devices; @bem22 your issue is likely different than @chrishunt93 's since the example in this ticket is using BGAPI.

I unfortunately don't have any high rate BLE devices like this, so I haven't done and am not planning on doing any performance testing, but I would welcome PRs if you made any progress.