PythonIDE Docs
中文
简体中文

bluetooth

BLE 扫描、连接、服务发现和特征读写。

BLE 中心模式:扫描外设、连接、发现服务、读写特征值。

边界:面向低功耗蓝牙中心端(扫描/连接其他设备),不是普通 HTTP/WebSocket 网络。若要让本机被扫描,请用 ble_peripheral。需要蓝牙硬件与系统授权;扫描、连接放在按钮回调,不要在 body() 里自动执行。

#模块概览

说明
导入import bluetooth
适合做什么传感器读取、Beacon 探测、自定义 BLE 外设通信
调用时机scan / connect / read / write 放在按钮回调
推荐顺序state()scan()connect()discover_services() → 读写 → disconnect()
数据格式write() 传 Base64 字符串;read() 返回 Base64

#快速开始

下面脚本检查蓝牙状态并扫描 5 秒:

python
import bluetooth

print("状态:", bluetooth.state())
if bluetooth.state() == "powered_on":
    devices = bluetooth.scan(duration=5)
    for d in devices:
        print(d.get("name"), d.get("uuid"), d.get("rssi"))
else:
    print("蓝牙不可用,请到设置中开启")

连接并发现服务:

python
import bluetooth

if bluetooth.state() == "powered_on":
    devices = bluetooth.scan(duration=5.0)
    if devices:
        uuid = devices[0]["uuid"]
        result = bluetooth.connect(uuid)
        if result == "ok":
            try:
                services = bluetooth.discover_services(uuid)
                print(f"发现 {len(services)} 个服务")
            finally:
                bluetooth.disconnect(uuid)
        else:
            print("连接失败:", result)

#AppUI 示例

扫描、连接分步放在按钮回调;失败时保留可读状态。

python
import appui
import bluetooth

state = appui.State(
    ble_state="—",
    device_count="0",
    status="未扫描",
    detail="点击扫描开始",
)

session = {"uuid": None}


def refresh_ble_state():
    state.ble_state = str(bluetooth.state())


def scan_devices():
    refresh_ble_state()
    if state.ble_state != "powered_on":
        state.batch_update(
            status="蓝牙不可用",
            detail=f"当前: {state.ble_state}",
            device_count="0",
        )
        return

    devices = bluetooth.scan(duration=5.0) or []
    state.device_count = str(len(devices))
    if not devices:
        state.batch_update(
            status="未发现设备",
            detail="请靠近外设后重试",
        )
        return

    target = devices[0]
    session["uuid"] = target.get("uuid")
    name = target.get("name") or "未命名设备"
    state.batch_update(
        status="已发现设备",
        detail=f"{name} · RSSI {target.get('rssi', '—')}",
    )


def connect_first():
    uuid = session.get("uuid")
    if not uuid:
        state.detail = "请先扫描"
        return

    result = bluetooth.connect(uuid)
    if result != "ok":
        state.batch_update(status="连接失败", detail=str(result))
        return

    services = bluetooth.discover_services(uuid) or []
    state.batch_update(
        status="已连接",
        detail=f"{len(services)} 个服务",
    )


def disconnect_device():
    uuid = session.get("uuid")
    if uuid:
        bluetooth.disconnect(uuid)
    session["uuid"] = None
    state.batch_update(status="已断开", detail="连接已释放")


def body():
    return appui.NavigationStack(
        appui.Form([
            appui.Section("蓝牙", [
                appui.LabeledContent("系统状态", value=state.ble_state),
                appui.LabeledContent("扫描结果", value=state.device_count),
                appui.Button("刷新状态", action=refresh_ble_state),
                appui.Button("扫描设备", action=scan_devices)
                .button_style("bordered_prominent"),
                appui.Button("连接第一个", action=connect_first),
                appui.Button("断开", action=disconnect_device, role="destructive"),
            ]),
            appui.Section("详情", [
                appui.LabeledContent("状态", value=state.status),
                appui.Text(state.detail).foreground_color("secondaryLabel"),
            ], footer="真机测试;示例只连扫描到的第一台设备。"),
        ]).navigation_title("蓝牙")
    )


appui.run(body, state=state)

#API 参考

#速查

API作用
state()BLE 状态字符串
scan(duration)扫描外设列表
stop_scan()立即停止扫描
connect(uuid)连接 → ok 或错误信息
disconnect(uuid)断开连接
discover_services(uuid)服务与特征列表
read(...)读特征 → Base64 字符串
write(...)写特征(Base64 入参)→ bool

#状态与扫描

state() 常见返回值:

含义
powered_on蓝牙已开启,可扫描
powered_off蓝牙关闭
unauthorized未授权
unsupported设备不支持 BLE

scan(duration=5.0) — 返回 [{uuid, name, rssi}, ...]

python
devices = bluetooth.scan(duration=3.0)
bluetooth.stop_scan()  # 提前结束

#连接与发现

connect(uuid) — 成功返回 "ok",失败返回错误描述字符串(不是异常)。

discover_services(uuid) — 返回服务字典列表(含特征 UUID),须先连接成功。

#读写特征

python
import base64

data_b64 = bluetooth.read(peripheral_uuid, service_uuid, char_uuid)
raw = base64.b64decode(data_b64) if data_b64 else b""

payload = base64.b64encode(b"hello").decode("ascii")
ok = bluetooth.write(peripheral_uuid, service_uuid, char_uuid, payload)

write() 的第四个参数必须是 Base64 字符串,不要直接传 bytes

#推荐流程

  1. state() 确认 powered_on
  2. scan() 找到目标 uuid
  3. connect(uuid)
  4. discover_services(uuid) 获取 service_uuid / characteristic_uuid
  5. read() / write()
  6. disconnect(uuid)(建议 try/finally

#常见错误

错误写法后果修正
判断 poweredOn永远不匹配使用 powered_on
write() 直接传 bytes类型错误base64.b64encode
不检查 connect 返回值未连接就读写判断 == "ok"
忘记 disconnect()连接残留finally 里断开
body()scan()刷新时反复扫描耗电放进按钮回调
ble_peripheral 混淆调错 API广播用外设模块

#相关文档

文档用途
ble_peripheral本机作为 BLE 外设广播
networkHTTP 网络请求
websocketWebSocket 连接
permission蓝牙权限状态查询
原生能力入口MiniApp 场景配方

#预期效果

运行示例后,界面应出现文档描述的目标结果;若与预期不符,先看「失败路径」并按返回值或日志排查。