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
相关产品推荐
相关产品推荐

