Skip to main content

A professional Python Bluetooth Host stack for testing, simulation and protocol education.

Project description

PyBlueHost

面向测试、仿真和协议教学的专业级 Python 蓝牙 Host 协议栈。

PyBlueHost 用纯 Python 实现完整的 Bluetooth Host 协议栈:HCI、L2CAP、ATT/GATT、SMP、SDP、RFCOMM,以及 BLE 与 Classic 双模 GAP —— 全部基于 asyncio 构建。
适用于快速原型开发、协议学习、无硬件集成测试,以及编写自定义 BLE/Classic profile 服务端与客户端。

  • 纯 Python 3.10+,asyncio 原生
  • 支持虚拟硬件 —— 内置 VirtualController,可在单元测试中跑完整协议栈
  • 多种 Transport —— UART、USB(PyUSB)、TCP、UDP、btsnoop replay、Linux HCI user-channel
  • YAML-driven service definitions —— 声明式定义自定义服务,无需手写 handler 样板
  • 结构化 Trace —— HCI 包按命令/事件名展开(带 SIG 查表),可彩色实时输出,也可录制为 btsnoop / JSON Lines

我属于哪一类用户?

PyBlueHost 服务三类不同需求的用户。先确定自己属于哪类,直接跳到对应章节:

你的目标 你属于 跳到
验证适配器、抓 trace、跑 demo —— 不写代码 协议测试/分析用户 一、CLI 用户篇
写自己的 BLE/Classic 应用:自定义 GATT service、SPP 私有协议、自动化脚本 —— pip install pybluehost 当依赖,不改 PyBlueHost 源码 应用开发用户 二、应用开发者篇
修协议 bug、加 LE Audio / A2DP、加新 vendor / 新 transport —— git clone 后做二次开发 协议栈贡献者 三、协议栈贡献者篇

已测试硬件

芯片型号 VID PID Transport 协议版本 类型 备注
RTL8852BE 0x0BDA 0x4853 USB 5.2 BR/EDR + BLE rtl8852bu_fw.bin
CSR8510 0x0A12 0x0001 USB 4.0 BR/EDR + BLE 只支持BT 4.0
Intel BE200 0x8087 0x0036 USB 5.4 BR/EDR + BLE ibt-0291-0291.sfi
BARROT BT6.0 0x33FA 0x0012 USB 6.0 BR/EDR + BLE UGREEN BT6.0 Adapter
nRF52840 0x1915 0x521F UART 5.4 BLE PTS FW

CSR、Intel 系列芯片在代码中已支持但未在本仓库做完整回归。欢迎提 PR 补 hardware 矩阵。


一、CLI 用户篇(协议测试与分析)

适合:拿到适配器想验证蓝牙功能、跑 demo、抓 trace、用 PyBlueHost 当临时 host 验证场景的人。 全程不需要写代码,CLI 命令就够。

1.1 安装

pip install pybluehost      # 包含运行 CLI 所需的全部依赖

依赖说明:

用途
cryptography SMP 配对加密(AES/CMAC/ECDH)
pyserial-asyncio UART transport
pyusb + libusb-package USB transport(Windows 自带 libusb-1.0.dll)
pyyaml Profile YAML 服务定义

如果你用的是 git clone 而不是 pip install,记得 git submodule update --init 拉取 SIG assigned-numbers 数据库(company_id / UUID / AD type 名字查表用)。

1.2 第一次跑:列出硬件 + 诊断

# 列出所有的USB transport(仅USB transport, 不包括UART/TCP/UDP...)
pybluehost --list-transport

# USB 设备探测和驱动诊断(不打开设备,只读 USB 描述符)
pybluehost tools usb probe
pybluehost tools usb probe --verbose

# 完整诊断(尝试打开设备/检查驱动/检查是否需要load fw/测试hci reset,给出"为什么打不开"的具体原因)
pybluehost tools usb diagnose

1.3 BLE 验证(CLI)

--transport 接受 virtualusb:VID:PIDuart:COM5[@115200]uart:/dev/ttyUSB0[@921600]。USB 请直接使用 pybluehost tools usb probe 输出的 Transport Names,例如 usb:33FA:0012;同一电脑上有两个相同 VID/PID 设备时使用 #1#2 区分,例如 usb:8087:0036#1--btsnoop 使用btsnoop格式记录hci log。
--hci-log 终端中实时显示hci raw log。

# 扫描周围 BLE 设备(长跑,Ctrl+C 结束)
pybluehost app ble-scan --transport usb
pybluehost app ble-scan --transport usb:8087:0036#1
pybluehost app ble-scan --transport uart:COM5@115200
# 添加 HCI btsnoop log
pybluehost app ble-scan --transport usb --btsnoop btsnoop.cfa
# 添加 HCI raw log
pybluehost app ble-scan --transport usb --hci-log

# 自己也广播让别的设备看到
pybluehost app ble-adv --transport usb --name MyDevice

# 起一个 GATT server,让手机能连过来
pybluehost app gatt-server --transport usb

# Heart Rate Sensor demo(带 notification 推送)
pybluehost app hr-monitor --transport usb

# 一次性:浏览远端 GATT 数据库(services / characteristics / descriptors / properties)
# 地址格式:`A0:90:B5:10:40:82` 或 `A090B5104082` 都接受。
pybluehost app gatt-browser --transport usb --addr A0:90:B5:10:40:82

1.4 Classic 蓝牙验证(CLI)

# 经典蓝牙设备发现
pybluehost app classic-inquiry --transport usb

# SPP 服务(手机蓝牙串口终端连过来发字符串,会原样 echo 回去)
pybluehost app spp-echo --transport usb

# 一次性:浏览远端 SDP records
pybluehost app sdp-browser --transport usb --addr 1A:8D:8D:1B:F5:6B
pybluehost app sdp-browser --transport usb --addr 1A8D8D1BF56B --uuid 0x1101

1.5 本地 UART/USB HCI transport 转接成网络 TCP/UDP H4 前端

pybluehost app bridge --transport usb --btsnoop test.cfa pybluehost app bridge --transport uart:/dev/ttyUSB0@921600 --protocol udp --port 57123

UART 使用统一 transport 规则 uart:<port>[@baud];Windows 串口可写作 uart:COM5@921600

1.6 离线工具(不需要硬件)

# HCI 包十六进制 → 解码后的命令/事件
pybluehost tools decode 01030c00

# Resolvable Private Address(IRK / RPA / 验证)
pybluehost tools rpa gen-irk
pybluehost tools rpa gen-rpa --irk <32-hex>
pybluehost tools rpa verify --irk <32-hex> --addr AA:BB:CC:DD:EE:FF

# USB 蓝牙芯片固件管理
pybluehost tools fw list
pybluehost tools fw download <chip>

1.7 出问题怎么调试(trace)

最常用的三个命令:

# 看 HCI 包的实时人读输出(彩色单行)
pybluehost --trace=hci app hr-monitor --transport=usb

# 出现握手失败 / 配对失败时 → 全层 debug,看协议层每一步
pybluehost --trace=*=debug app hr-monitor --transport=usb 2> trace.log

# 给 maintainer 提 issue 时,附上的两个文件
ls pybluehost.log     # 默认日志文件
ls trace.log          # 你刚才重定向的 trace

输出长这样(成功事件单行,错误自动展开多行):

↓ HCI Cmd  HCI_LE_Set_Scan_Params
↑ HCI Evt  Command_Complete                 op=0x200B status=Success
↑ HCI Evt  LE_Advertising_Report            Random F8:1A:94:1D:5C:62 rssi=-67 dBm
↑ HCI Evt  Command_Complete                 op=0x200C status=Invalid_HCI_Command_Parameters(0x12)
                                            ├── num_hci_command_packets = 1
                                            ├── command_opcode          = 0x200C
                                            └── status                  = 0x12 (Invalid_HCI_Command_Parameters)

需要更细的控制(按层独立级别、ACL payload 不截断、把默认抑制的事件加回来)见 §3.4 「Trace 系统深度定制」。

1.8 安装 / 硬件常见问题

Windows:必须装 WinUSB 驱动

USB transport 在 Windows 上需要把目标适配器替换为 WinUSB 驱动。libusb-package 解决了 DLL 查找问题,但驱动绑定无法绕过 —— 用 Zadig 替换。

Linux:USB 权限 Operation not permitted

# 临时方案:sudo 跑(不推荐长期)
sudo pybluehost app ble-scan --transport=usb

# 永久方案:加 udev 规则(以 Realtek RTL8852BE 为例)
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="4853", MODE="0666"' \
  | sudo tee /etc/udev/rules.d/99-pybluehost.rules
sudo udevadm control --reload-rules && sudo udevadm trigger
# 拔插一次设备

Linux:bluez 守护进程占着设备

sudo systemctl stop bluetooth         # 临时
sudo systemctl disable bluetooth      # 长期(如果你只用 PyBlueHost)

或者用 HCI user-channel transport 直接通过内核 socket 而不抢 BlueZ:见 pybluehost.transport.hci_user_channel.HCIUserChannelTransport

macOS:Apple 的蓝牙栈占着内置控制器

macOS 上系统蓝牙 daemon 排他持有内置控制器;外接 USB 适配器才能让 PyBlueHost 用上。

SIG 名字显示成 hex 而不是名字

git clone 安装时漏了 submodule。跑:

git submodule update --init

pip install pybluehost 包里已经把 SIG 数据打进去了,不会有这个问题。


二、应用开发者篇(基于 PyBlueHost 写蓝牙应用)

适合:在 PyBlueHost 上写自己的 BLE/Classic 应用 —— 自定义 GATT service、SPP 私有协议、自动化测试脚本。 pip install pybluehost 当依赖,不改 PyBlueHost 源码;大部分时候你只在最上层写代码。

2.1 安装 + 第一行代码

pip install pybluehost
# hello_pybluehost.py
import asyncio
from pybluehost import Stack

async def main():
    async with await Stack.virtual() as stack:
        print(f"Local address: {stack.local_address}")
        # stack.gap, stack.gatt_server, stack.l2cap, stack.hci, stack.trace 全部就绪

asyncio.run(main())
python hello_pybluehost.py
# Local address: AA:BB:CC:XX:YY:ZZ

Stack.virtual() 基于 VirtualController 构建一个完整协议栈 —— 不需要任何蓝牙硬件,所有 HCI 命令都在进程内仿真器中流转,方便起步和写自动化测试。

2.2 启动协议栈(virtual / 真硬件)

from pybluehost import Stack

# 虚拟环境(无硬件)—— 写测试 / 起步首选
async with await Stack.virtual() as stack:
    ...

# USB 自动探测(按 vendor 过滤可避免多块适配器选错)
async with await Stack.from_usb(vendor="intel") as stack:
    ...

# UART
async with await Stack.from_uart(port="/dev/ttyUSB0", baudrate=921600) as stack:
    ...

StackConfig 控制设备级默认值:

from pybluehost import StackConfig
from pybluehost.core.types import IOCapability
from pybluehost.ble.security import SecurityConfig

config = StackConfig(
    device_name="MyDevice",
    appearance=0x0341, # Heart Rate Sensor
    le_io_capability=IOCapability.DISPLAY_YES_NO,
    security=SecurityConfig(
        bondable=True, mitm_required=True, secure_connections=True,
    ),
    command_timeout=5.0,
)
async with await Stack.virtual(config=config) as stack:
    ...

你写代码主要用到的 stack 入口

属性 干什么的
stack.gap BLE + Classic 统一 GAP(广播/扫描/inquiry/连接/可发现性/SSP)
stack.gatt_server 注册自定义 GATT service / 内置 profile
stack.gatt_client 服务发现 / 读写 / 订阅 notification
stack.sdp Classic SDP records 注册 + 查询
stack.rfcomm RFCOMM channel listen / connect(SPP 基础)
stack.l2cap L2CAP CoC(应用一般不直接用)
stack.trace 挂自定义 sink 录 trace(见 §2.6)
stack.local_address 本机 BD_ADDR

2.3 写一个 BLE GATT Server

自定义 service(用装饰器驱动的 profile 框架,省略 imports):

from pybluehost.core.uuid import UUID16
from pybluehost.profiles.ble import BLEProfileServer
from pybluehost.profiles.ble.decorators import on_read, on_write, on_notify

class MyTemperatureService(BLEProfileServer):
    service_uuid = UUID16(0x1809)  # Health Thermometer

    def __init__(self):
        self._temp = 250  # 25.0°C, units 0.1°C

    @on_read(UUID16(0x2A1C))
    async def read_temp(self) -> bytes:
        return self._temp.to_bytes(2, "little")

    @on_write(UUID16(0x2A1C))
    async def write_temp(self, value: bytes) -> None:
        self._temp = int.from_bytes(value, "little")

    @on_notify(UUID16(0x2A1C))
    async def notify_temp(self) -> bytes:
        return self._temp.to_bytes(2, "little")

# 注册:
service = MyTemperatureService()
await service.register(stack.gatt_server)

用现成的内置 profile

from pybluehost.profiles.ble import BatteryServer, HeartRateServer

battery = BatteryServer(initial_level=85)
hrs = HeartRateServer(sensor_location=0x02)  # 手腕
await battery.register(stack.gatt_server)
await hrs.register(stack.gatt_server)

await hrs.update_measurement(bpm=72)   # 推送一次 notification

可用的内置 Profile:BatteryServer/ClientHeartRateServer/ClientDeviceInformationServer/ClientBloodPressureServerHIDServerRSCServerCSCServerGAPServiceServerGATTServiceServer

参考真实代码:pybluehost/profiles/ble/battery.pyheart_rate.pyhids.py(每个文件 < 50 行,照抄改造即可)。

2.4 写一个 BLE 客户端

pybluehost/cli/app/gatt_browser.py 是完整可运行的客户端示例(约 100 行)—— 扫描、连接、发现 services、按字段格式化打印。下面是缩微版:

from pybluehost.profiles.ble import BatteryClient

async with await Stack.virtual() as stack:
    # 通过 stack.gap.ble_connections.connect(...) 建立连接
    gatt_client = ...     # 从已连接的 GATTClient 获得

    battery = BatteryClient()
    await battery.discover(gatt_client)
    level = await battery.read_battery_level()
    print(f"Remote battery: {level}%")

2.5 写一个 Classic 应用(SDP/RFCOMM/SPP)

from pybluehost.classic.gap import InquiryConfig

async with await Stack.virtual() as stack:
    # 设备发现
    await stack.gap.classic_discovery.start(InquiryConfig(duration=8))

    # 设置可发现 + 可连接
    await stack.gap.classic_discoverability.set_discoverable(True)
    await stack.gap.classic_discoverability.set_device_name("MyDevice")

    # SDP / RFCOMM 通过下列入口访问
    # stack.sdp, stack.rfcomm

完整 SPP echo server 示例:pybluehost/cli/app/spp_echo.py

2.6 在自己的代码里挂 trace

PyBlueHost 内置结构化 trace 系统,所有 HCI/L2CAP 包都流经 stack.trace。挂接 sink 即可录制成文件:

from pybluehost import Stack, StackConfig
from pybluehost.core.trace import BtsnoopSink, JsonSink

config = StackConfig(
    trace_sinks=[
        BtsnoopSink("session.btsnoop"),   # Wireshark 兼容
        JsonSink("session.jsonl"),        # 每行一个 JSON 对象
    ],
)
async with await Stack.virtual(config=config) as stack:
    # ... 业务代码 ...
    pass  # close() 会自动 flush 所有 sink

回放已抓取的 btsnoop

from pybluehost.transport.btsnoop import BtsnoopTransport

transport = BtsnoopTransport(path="capture.btsnoop", realtime=False)
# 与普通 transport 一样使用 —— 包从文件中按序注入

需要更深的定制(自定义 sink、按层级别精细控制、防刷屏配置)见 §3.4

2.7 给自己的应用写测试

应用开发者最常用 Stack.virtual() 写无硬件单元测试。基本模板:

# tests/test_my_app.py
import pytest
from pybluehost import Stack
from my_app import MyTemperatureService

@pytest.mark.asyncio
async def test_temperature_service_reads_correctly():
    async with await Stack.virtual() as stack:
        svc = MyTemperatureService()
        await svc.register(stack.gatt_server)

        # 通过 stack.gatt_server.db 直接查 attribute(白盒)
        # 或起 peer_stack 真连过来读(端到端)
        ...
pip install pytest pytest-asyncio
pytest tests/

配置(你自己 pyproject.toml):

[tool.pytest.ini_options]
asyncio_mode = "auto"

2.8 应用开发常见入口速查

我想做的事 看这里
加一个新 BLE Service / Profile pybluehost/profiles/ble/(参考 battery.py / heart_rate.py 这些短文件)
写一个客户端浏览远端 GATT pybluehost/cli/app/gatt_browser.py(约 100 行,完整可运行)
起 SPP echo server pybluehost/cli/app/spp_echo.py
起 Heart Rate notification 服务 pybluehost/cli/app/hr_monitor.py
自定义事件 callback / 录 trace §2.6 在自己的代码里挂 trace
想改协议栈本身(HCI / L2CAP / GATT 内部) 你不属于这一篇,去看 三、协议栈贡献者篇

三、协议栈贡献者篇(修改 PyBlueHost 源码)

适合:修协议 bug、加 LE Audio / A2DP、加新 vendor / 新 transport、加 SMP 高级特性等需要改 PyBlueHost 源码的人。 全程在 git clone 出来的源码树里干活,跑测试用 uv run pytest

3.1 开发环境安装

PyBlueHost 用 uv 管理依赖。

# 1. 克隆仓库 + 拉 submodule
git clone https://github.com/gitdreambox/pybluehost.git
cd pybluehost
git submodule update --init   # SIG assigned-numbers 数据库

# 2. 安装开发依赖(含 pytest、pytest-asyncio、pytest-cov)
uv sync --extra dev

# 3. 验证开发环境
uv run pytest tests/ --transport=virtual

3.2 架构与代码导航

分层

┌─────────────────── Profiles (Battery, HRS, HID, ...) ───────────────────┐
│  ↑ 应用开发用户的代码大多在这一层                                         │
├──── GAP (BLE + Classic 统一入口) ──┬── GATT ────┬── SDP ─── RFCOMM ─────┤
│                                     │            │                       │
│           ATT ─ SMP                 │            │                       │
├─────────────────────────── L2CAP ───────────────────────────────────────┤
├─────────────────────── HCI(命令、事件、ACL、流控)──────────────────────┤
└─────────────── Transport (UART, USB, TCP, UDP, btsnoop, virtual) ───────┘

调用方向:应用代码调 stack.gap / stack.gatt_server / stack.sdp / stack.rfcomm,下层一直传到 transport;事件反向上来,HCI controller 解码后通过 callback / channel 上送到对应层。

目录树

pybluehost/
├── core/             # 通用基础:address、UUID、errors、状态机、trace、SIG DB
├── transport/        # UART / USB / TCP / UDP / btsnoop / HCI user-channel
├── hci/              # HCI packet codec、流控、controller、virtual controller、vendor
│   ├── format.py     # HCI 包人读字符串渲染
│   └── format_fields.py
├── l2cap/            # SAR、固定/CoC channel、ERTM、信令
├── ble/              # ATT / GATT / SMP / SecurityConfig
├── classic/          # SDP / RFCOMM / SPP / Classic GAP
├── gap.py            # BLE + Classic 统一 GAP 入口
├── profiles/ble/     # 9 个内置 profile + 装饰器框架
├── stack.py          # Stack 工厂 / 生命周期 / TraceSystem 启动
└── cli/
    ├── app/          # 8 个 BT 功能命令(每个一文件,~50-150 行,可读)
    └── tools/        # 4 个离线工具(decode / rpa / fw / usb)

二次开发常见入口

我想做的事 看哪儿
改 HCI 命令处理 / vendor 命令 pybluehost/hci/
加新 transport(BlueZ 内核 socket、TCP-over-WebSocket 等) pybluehost.transport.base.Transport 接口(参考 udp.py 最短)
加新 vendor 固件加载流程 pybluehost/transport/usb.py(已有 Intel / Realtek / CSR 三家可参考)
L2CAP 改 ERTM / Streaming mode pybluehost/l2cap/
ATT/GATT 协议变化(spec 更新) pybluehost/ble/att.py / gatt.py
SMP 新加密算法 / Secure Connections 变体 pybluehost/ble/smp/
Classic 加 A2DP / AVRCP / HFP profile 新建 pybluehost/classic/<profile>.py + pybluehost/profiles/classic/

详细文档

3.3 跑测试套件(完整版)

测试默认自动检测 USB 蓝牙适配器;找不到时回落到 virtual(软件仿真)。

# 全套(默认自动检测)
uv run pytest tests/

# 强制 virtual(CI 用)
uv run pytest tests/ --transport=virtual

# 指定子目录
uv run pytest tests/unit/ble/ -v
uv run pytest tests/unit/profiles/ -v

# 仅 btsnoop 回放测试
uv run pytest -m btsnoop

# 带覆盖率
uv run pytest tests/ --transport=virtual --cov=pybluehost --cov-report=term-missing

# 真硬件(按 vendor 过滤)
uv run pytest tests/ --transport=usb:0A12:0001#1

# UART
uv run pytest tests/ --transport=uart:/dev/ttyUSB0@921600

# 双适配器测试(peer 自动找第二块;找不到则跳过)
uv run pytest tests/ --transport=usb:0A12:0001#1 --transport-peer=usb:0A12:0001#2

# pytest 内打开 trace(注意:pytest 选项叫 --pybluehost-trace 不叫 --trace)
uv run pytest tests/ --pybluehost-trace=hci --transport=virtual

# 通过环境变量
PYBLUEHOST_TEST_TRANSPORT=usb:0A12:0001#1 uv run pytest tests/

# 列出所有检测到的适配器
uv run pytest --list-transports

测试可以用 @pytest.mark.real_hardware_only@pytest.mark.virtual_only 限制运行环境。Marker 分组:unit / integration / e2e / btsnoop / slow / real_hardware_only / virtual_only

3.4 Trace 系统深度定制

PyBlueHost 内置结构化 trace 系统:HCI 包按命令/事件名展开(含字段、SIG company name 等查表),按层独立可控,彩色实时输出到 stderr。默认零开销 —— 不指定 --trace / 不挂 sink 时不做任何额外工作。

应用开发用户的基本用法见 §2.6;本节是协议栈贡献者级别的深定制。

CLI / 环境变量控制

pybluehost --trace=hci app gatt-browser --transport=virtual            # HCI 层 INFO
pybluehost --trace=hci=debug,l2cap app gatt-browser --transport=usb    # HCI debug + L2CAP info
pybluehost --trace=*=debug app gatt-browser --transport=virtual        # 全部层 debug
pybluehost --trace=hci,full-acl app spp-echo --transport=usb           # ACL 不截断
pybluehost --trace=hci,include=Number_Of_Completed_Packets ...         # 把默认静音的事件加回来

PYBLUEHOST_TRACE=hci=debug pybluehost app ...                          # env var 同样生效

Spec 语法(--trace / PYBLUEHOST_TRACE 共用)

形式 含义
<layer> 该层 INFO 级
<layer>=info / <layer>=debug 显式级别
* / *=debug 通配所有层
<layer1>,<layer2>=debug,... 多层、各自级别,逗号分隔
,full-acl ACL data 不截断(默认 24 字节)
,include=<EventName> 把默认抑制的事件加回来

层名字hcism(state machine)、transportl2capattgattsmpsdprfcommgap

颜色

ANSI 颜色按业界惯例自动决定(与 gitgrepbat 一致):

  • 默认:stderr 是 TTY 时上色;重定向到管道/文件自动关
  • NO_COLOR=1 强制关闭
  • FORCE_COLOR=1 强制开启(CI 抓彩色日志用)

防刷屏默认

事件 默认行为 关闭抑制
Number_Of_Completed_Packets(HCI flow control) 完全静默 --trace=hci,include=Number_Of_Completed_Packets
LE_Advertising_Report(同地址重复) 折叠为一行 --trace=hci,include=LE_Advertising_Report
ACL data 长 payload 截断为前 24 字节 --trace=hci,full-acl

协议层 logger

L2CAP / ATT / GATT / SMP / SDP / RFCOMM / Classic GAP+SSP / HCI Connection 共约 40 个关键决策点会输出 INFO/WARN/DEBUG(连接开关、MTU exchange、Error_Response、pairing 阶段、inquiry 等)。它们走标准 Python logging,由 --trace=<layer>=<level> 调级别。

输出会同时进 pybluehost.log 文件(受 --log-file / --log-level 控制)。

编程方式安装 trace

from pybluehost.core import (
    parse_trace_spec, trace_install,    # one-shot install
    apply_logging_levels, attach_console_sink,    # 拆分版本
)

stack = await Stack.virtual()
spec = parse_trace_spec("hci=debug,l2cap")
trace_install(spec, stack.trace)        # 给该 stack 挂 ConsoleSink + 调 logger 级别

写自定义 sink

实现 pybluehost.core.trace.TraceSink 协议(一个 async def consume(event: TraceEvent) 方法):

from pybluehost.core.trace import TraceSink, TraceEvent

class MyMetricsSink(TraceSink):
    async def consume(self, event: TraceEvent) -> None:
        # 把每个 HCI 包统计到 prometheus / push 到 Kafka 等等
        if event.layer == "hci":
            metrics.counter(f"hci.{event.kind}").inc()

config = StackConfig(trace_sinks=[MyMetricsSink()])

3.5 Plan 驱动开发流程

PyBlueHost 用 plan 驱动的实施模式:每个新功能先写 spec → 评审 → 写 plan → 一个 task 一个 task 跑 → 状态更新到 STATUS.md

完整流程见 CLAUDE.md。关键文件:

提 PR 前最少跑:

uv run pytest tests/ --transport=virtual --cov=pybluehost --cov-fail-under=85

项目状态

全部 18 个实施 Plan 均已完成:

  • Core 层 —— address、UUID、errors、状态机、trace、SIG 数据库
  • Transport 层 —— UART、USB、TCP、UDP、virtual、btsnoop 回放、HCI user-channel
  • HCI 层 —— packet codec、流控、controller、virtual controller、vendor(Intel/Realtek)
  • L2CAP 层 —— SAR、固定/CoC 通道、ERTM、信令、manager
  • BLE —— ATT、GATT(server + client)、SMP、SecurityConfig、GAP(广播/扫描/连接/隐私/白名单)
  • Classic —— SDP、RFCOMM、SPP、GAP(inquiry/SSP/可发现性)
  • Profiles —— 9 个内置 BLE Profile + 装饰器驱动的自定义 Profile 框架
  • Stack 装配 —— Stack 工厂,支持 virtual 模式与 async 上下文管理器
  • 测试基础设施 —— 1000+ 测试,覆盖率 86%+,btsnoop 回放,CI 矩阵(Python 3.10/3.11/3.12)
  • CLI 工具 —— apptools 双命名空间共 12 个子命令
  • Pytest Transport 选择 —— --transport--list-transports、自动 USB 探测 + 回落
  • 结构化 Trace —— ConsoleSink(彩色、防刷屏)、SIG 查表格式化器、协议层 logger 注入

许可证

MIT —— 详见 LICENSE(如存在)或 pyproject.toml


贡献

开发流程基于 plan 驱动的实施模式。贡献者指南见 CLAUDE.md,任务看板见 docs/superpowers/STATUS.md

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pybluehost-0.9.9.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pybluehost-0.9.9-py3-none-any.whl (1.2 MB view details)

Uploaded Python 3

File details

Details for the file pybluehost-0.9.9.tar.gz.

File metadata

  • Download URL: pybluehost-0.9.9.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.19

File hashes

Hashes for pybluehost-0.9.9.tar.gz
Algorithm Hash digest
SHA256 70593b9c7c6da4058844d991eb64111601bfd453eba58a63cc1cc9e2737709c4
MD5 37200c5a043d866624e466c2e2e2602b
BLAKE2b-256 2b3d41e4b6f961ed1ef36cfcac39ec093e06fef5c8b709dd2049ebf7494e1f0a

See more details on using hashes here.

File details

Details for the file pybluehost-0.9.9-py3-none-any.whl.

File metadata

  • Download URL: pybluehost-0.9.9-py3-none-any.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.19

File hashes

Hashes for pybluehost-0.9.9-py3-none-any.whl
Algorithm Hash digest
SHA256 13c8656a763bd1fe381941eaf493a1b2dc8b915ea1043ad99149baab97d3bc24
MD5 77149b4ef7cad7f8c372fb4cf9f50de9
BLAKE2b-256 c524601ef5caefeb371be166cf5bceecdb6079f8b3b8c05d26cf204f6db7fc43

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page