Python 基础脚本:使用 Bleak 列出 BLE 设备

此脚本使用 Python 的 Bleak 库列出蓝牙低功耗 (BLE) 设备。目前,RSSI 和服务列表不起作用

list_ble_devices.py
#!/usr/bin/env python3
"""
BLE 设备扫描器

此脚本扫描并列出附近所有可用的蓝牙低功耗 (BLE) 设备。
它显示设备信息,包括名称、地址和 RSSI。

要求:
    - bleak 库:pip install bleak

用法:
    python list_ble_devices.py
"""

import asyncio
import sys
from bleak import BleakScanner
from datetime import datetime


async def scan_ble_devices(scan_time=10):
    """
    扫描 BLE 设备并返回已发现设备的列表。

    参数:
        scan_time (int): 扫描持续时间(秒)(默认:10)

    返回:
        list: BleakDevice 对象列表
    """
    print(f"Scanning for BLE devices for {scan_time} seconds...")
    print("=" * 50)

    try:
        devices = await BleakScanner.discover(timeout=scan_time)
        return devices
    except Exception as e:
        print(f"Error during scanning: {e}")
        return []


def display_devices(devices):
    """
    以格式化表格显示已发现的 BLE 设备。

    参数:
        devices (list): BleakDevice 对象列表
    """
    if not devices:
        print("No BLE devices found.")
        return

    print(f"Found {len(devices)} BLE device(s):")
    print("-" * 80)
    print(f"{'Name':<25} {'Address':<20} {'RSSI':<6} {'Services'}")
    print("-" * 80)

    for device in devices:
        name = device.name if device.name else "<Unknown>"
        address = device.address
        rssi = "N/A"
        if hasattr(device, 'metadata') and 'rssi' in device.metadata:
            rssi_val = device.metadata['rssi']
            rssi = f"{rssi_val} dBm" if rssi_val is not None else "N/A"

        # 如果可用,获取服务 UUID
        services = ""
        if hasattr(device, 'metadata') and 'uuids' in device.metadata:
            services = ', '.join(device.metadata['uuids'][:2])  # 显示前 2 个 UUID
            if len(device.metadata['uuids']) > 2:
                services += "..."

        print(f"{name:<25} {address:<20} {rssi:<6} {services}")


async def main():
    """
    运行 BLE 设备扫描器的主函数。
    """
    print("BLE Device Scanner")
    print(f"Scan started at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print()

    # 检查是否提供了扫描时间作为命令行参数
    scan_time = 10
    if len(sys.argv) > 1:
        try:
            scan_time = int(sys.argv[1])
            if scan_time <= 0:
                raise ValueError("Scan time must be positive")
        except ValueError as e:
            print(f"Invalid scan time: {e}")
            print("Using default scan time of 10 seconds")
            scan_time = 10

    # 执行扫描
    devices = await scan_ble_devices(scan_time)

    # 显示结果
    print()
    display_devices(devices)

    # 附加设备详情
    if devices:
        print()
        print("Additional device information:")
        print("-" * 50)
        for i, device in enumerate(devices, 1):
            print(f"{i}. {device.name or '<Unknown>'} ({device.address})")
            metadata = getattr(device, 'metadata', None)
            if metadata:
                for key, value in metadata.items():
                    if key != 'uuids':  # uuids 已在上面显示
                        print(f"   {key}: {value}")
            print()


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\nScan interrupted by user.")
    except Exception as e:
        print(f"An error occurred: {e}")
        sys.exit(1)

Check out similar posts by category: Bluetooth, Python