bleak icon indicating copy to clipboard operation
bleak copied to clipboard

Scanning performance on Raspberry pi seems lower than on laptop

Open kazola opened this issue 1 year ago • 1 comments

  • bleak version: 0.20.2
  • Python version: 3.9
  • Operating System: Raspbian 11 Bullseye
  • BlueZ version (bluetoothctl -v) in case of Linux: 5.66 (we updated it)

Description

When scanning for ADV using Bleak on Raspberry, the amount of detected frames seems way lower than on laptop. The result averages provided by the following script are way higher, which leads me to think some ADV frames not being detected, thus increasing average calculation.

What I Did

I prepared a script that shows the average of time between ADVertisements for a BLE MAC.

import asyncio
import sys
import time
from bleak import BleakScanner, BLEDevice, BleakError


ael = asyncio.new_event_loop()
asyncio.set_event_loop(ael)
_g_dd = {}


def _summary():
    # calculate differences between contiguous ADV times
    def _diff(tt):
        diff_tt = []
        for x, y in zip(tt[0::], tt[1::]):
            diff_tt.append(y - x)
        return diff_tt

    global _g_dd
    # sort it by mac
    _ = list(_g_dd.keys())
    _.sort()
    _g_dd = {i: _g_dd[i] for i in _}

    # calculate average
    for k, tt in _g_dd.items():
        if len(tt) > 1:
            d = _diff(tt)
            v = int((sum(d) / len(d)) * 1000)
            d = [float('{:.4f}'.format(i)) for i in d]
            print('\n{}\n{:<3} | {:>5} ms {}'.format(k, len(d), v, d[:10]))
        else:
            # len = 1 means no diffs
            print('\n{}\n*'.format(k))

    # start fresh next time
    _g_dd = {}


async def ble_scan_mean_adv(t=20.0):

    # grab the scan duration parameter
    if len(sys.argv) == 2:
        t = float(sys.argv[1])

    def _scan_cb(d: BLEDevice, _):
        try:
            s = str(d.name)
        except (Exception,):
            return

        global _g_dd
        mac = d.address.lower()
        k = '{} {}'.format(mac, d.name)
        if k not in _g_dd.keys():
            _g_dd[k] = list()
        _g_dd[k].append(time.time())

    try:
        print("\nADV averager - scanning for {} seconds".format(int(t)))
        scanner = BleakScanner(_scan_cb, None)
        await scanner.start()
        await asyncio.sleep(t)
        await scanner.stop()
        _summary()

    except (asyncio.TimeoutError, BleakError, OSError) as ex:
        print("error BLE scan {}".format(ex))
        return []


if __name__ == '__main__':
    ael.run_until_complete(ble_scan_mean_adv())

Can anybody confirm this? If so, is there any parameter we can pass to "BleakScanner" to improve performance on RPi?

Thanks a lot and have a nice weekend :)

kazola avatar May 21 '23 08:05 kazola