You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32搭配MicroPython无法解析BLE设备名称求助

ESP32 MicroPython BLE扫描无法获取iPhone设备名称问题

我在ESP32的BLE模块搭配MicroPython环境下尝试解析iPhone(或其他设备)的名称,已经折腾两天还没解决。目前扫描只能得到这样的信息:

Device found: 0a:53:32:06:1d:b0 RSSI: -30 Name: None

我的PC能正常识别手机名称,手机也能识别PC名称,但ESP32就是获取不到设备名称!以下是我用的代码:

import bluetooth
from micropython import const
import time

_IRQ_SCAN_RESULT = const(5)
_IRQ_SCAN_DONE = const(6)
_COMPLETE_LOCAL_NAME_ADTYPE = const(0x09)
_SHORTENED_LOCAL_NAME_ADTYPE = const(0x08)

class BLEScanner:
    def __init__(self, ble, rssi_threshold):
        self.ble = ble
        self.ble.active(True)
        self.ble.irq(self.irq)
        self.rssi_threshold = rssi_threshold

    def irq(self, event, data):
        if event == _IRQ_SCAN_RESULT:
            addr_type, addr, adv_type, rssi, adv_data = data
            if rssi > self.rssi_threshold:
                name = self.parse_adv_data(adv_data)
                addr_str = ":".join("{:02x}".format(byte) for byte in addr)
                print("Device found:", addr_str, "RSSI:", rssi, "Name:", name)
        elif event == _IRQ_SCAN_DONE:
            print("Scan completed")

    def parse_adv_data(self, adv_data):
        i = 0
        name = None
        while i < len(adv_data):
            field_len = adv_data[i]
            if field_len == 0:
                break
            field_type = adv_data[i + 1]
            if field_type in (_COMPLETE_LOCAL_NAME_ADTYPE, _SHORTENED_LOCAL_NAME_ADTYPE):
                name = adv_data[i + 2:i + field_len + 1].decode()
                break
            i += field_len + 1
        return name

    def start_scan(self, duration_ms):
        self.ble.gap_scan(duration_ms, 30000, 30000, True)

def main():
    ble = bluetooth.BLE()
    scanner = BLEScanner(ble, -60)
    while True:
        print("Starting BLE scan...")
        scanner.start_scan(2000)
        time.sleep(4)

main()

问题解决办法

1. 检查iPhone的可发现状态

iPhone默认不会在BLE广播包中携带设备名称,只有当设备处于可被发现模式(打开蓝牙设置,确保设备名称下方显示“可被发现”)时,才会在广播数据中包含名称字段。先开启该模式再测试。

2. 调整扫描参数

代码中gap_scan的扫描间隔和窗口设为了30000ms(30秒),这会导致扫描频率极低,大概率错过携带名称的广播包。修改为更小的参数,比如:

self.ble.gap_scan(duration_ms, 10000, 10000, True)

将间隔和窗口调整为10秒以内,甚至5秒(5000ms),提升扫描覆盖率。

3. 排查广播数据解析逻辑

可以修改parse_adv_data函数,打印所有AD字段,确认设备是否发送了名称相关数据:

def parse_adv_data(self, adv_data):
    i = 0
    name = None
    while i < len(adv_data):
        field_len = adv_data[i]
        if field_len == 0:
            break
        field_type = adv_data[i + 1]
        field_data = adv_data[i + 2:i + field_len + 1]
        print(f"AD Type: {hex(field_type)}, Raw Data: {field_data}")
        if field_type in (_COMPLETE_LOCAL_NAME_ADTYPE, _SHORTENED_LOCAL_NAME_ADTYPE):
            name = field_data.decode()
            break
        i += field_len + 1
    return name

通过打印的信息,可以判断设备是否广播了名称字段,或者是否有其他AD类型存储了名称。

4. 主动连接获取设备名称

如果设备始终不在广播包中发送名称,可以尝试扫描到设备后主动连接,再请求远程名称:
首先添加连接相关的常量:

_IRQ_CONNECTED = const(2)
_IRQ_DISCONNECTED = const(3)

然后修改irq函数处理连接事件:

def irq(self, event, data):
    if event == _IRQ_SCAN_RESULT:
        addr_type, addr, adv_type, rssi, adv_data = data
        if rssi > self.rssi_threshold:
            name = self.parse_adv_data(adv_data)
            addr_str = ":".join("{:02x}".format(byte) for byte in addr)
            print("Device found:", addr_str, "RSSI:", rssi, "Name:", name)
            if name is None:
                # 尝试连接获取名称
                try:
                    self.ble.gap_connect(addr_type, addr)
                except Exception as e:
                    print(f"Connect failed: {e}")
    elif event == _IRQ_SCAN_DONE:
        print("Scan completed")
    elif event == _IRQ_CONNECTED:
        conn_handle, addr_type, addr = data
        addr_str = ":".join("{:02x}".format(byte) for byte in addr)
        # 请求远程设备名称
        try:
            remote_name = self.ble.gap_device_name(conn_handle)
            print(f"Connected device name: {remote_name} ({addr_str})")
        except Exception as e:
            print(f"Get name failed: {e}")
        # 断开连接
        self.ble.gap_disconnect(conn_handle)
    elif event == _IRQ_DISCONNECTED:
        print("Device disconnected")

内容的提问来源于stack exchange,提问作者Rowland Wetmaker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:23:19