蓝牙

广播 100ms 间隔高速率

import bluetooth, struct


#汉字一个3B,注意 最大8个汉字  100ms 广播高速率
def ble_name(dev_name):
    if len(dev_name)>26:
        return False
    ble = bluetooth.BLE()
    ble.active(False)
    ble.active(True)
    adv_data = struct.pack('BBB', 0x02, 0x01, 0x06)
    name_bytes = dev_name.encode()
    adv_data += struct.pack('B', 1 + len(name_bytes)) + b'\x09' + name_bytes
    ble.gap_advertise(None)
    ble.gap_advertise(100000, adv_data)
    print("广播启动,名称:", dev_name," 长度:",len(dev_name))
    return True

扫描 1s 定时版

from micropython import const
import bluetooth
import time

# 常量定义
_IRQ_SCAN_RESULT = const(5)
AD_TYPE_NAME_COMPLETE = const(0x09)
AD_TYPE_NAME_SHORT = const(0x08)

ble = bluetooth.BLE()
device_set = set()

def _parse_name(adv_data):
    i = 0
    while i < len(adv_data):
        ad_len = adv_data[i]
        if ad_len == 0:
            break
        ad_type = adv_data[i+1]
        payload = adv_data[i+2:i+1+ad_len]
        if ad_type in (AD_TYPE_NAME_COMPLETE, AD_TYPE_NAME_SHORT):
            try:
                return payload.decode("utf-8").strip()
            except:
                return "Unreadable"
        i += ad_len + 1
    return "NoName"

def _scan_callback(event, data):
    global device_set
    if event == _IRQ_SCAN_RESULT:
        _, _, _, _, adv_data = data
        name = _parse_name(bytes(adv_data))
        device_set.add(name)

def scan_ble_devices():
    """
    阻塞扫描1秒,返回周围蓝牙设备名称列表(去重)
    return: list[str]
    """
    global device_set
    device_set.clear()
    # 初始化蓝牙与回调
    ble.active(True)
    ble.irq(_scan_callback)
    # 扫描时长1000ms,高速抓包参数
    ble.gap_scan(1000, 30000, 28000, 1)
    # 阻塞等待最多1秒
    t_start = time.ticks_ms()
    while time.ticks_diff(time.ticks_ms(), t_start) < 1000:
        pass
    # 停止扫描、关闭蓝牙
    ble.gap_scan(None)
    ble.active(False)
    # 转列表返回
    return list(device_set)


# 调用示例
if __name__ == "__main__":
    names = scan_ble_devices()
    print("扫描到蓝牙设备:")
    for n in names:
        print("-", n)

#返回
#names = scan_ble_devices()

后台版本

开启服务 start_background_full_scan()然后返回扫描的设备列表 scan_ble_devices()

from micropython import const
import bluetooth
import time

# BLE常量
_IRQ_SCAN_RESULT = const(5)
AD_TYPE_NAME_COMPLETE = const(0x09)
AD_TYPE_NAME_SHORT = const(0x08)

ble = bluetooth.BLE()
# 存储结构 {设备名称: 最后收到广播时间戳}
dev_cache = dict()
SCAN_RUNNING = False
# 设备超时时间:1500ms未收到广播判定离开
DEV_TIMEOUT = 1500

def _parse_name(adv_data):
    """解析广播包中的蓝牙设备名称"""
    idx = 0
    data_len = len(adv_data)
    while idx < data_len:
        ad_len = adv_data[idx]
        if ad_len == 0:
            break
        ad_type = adv_data[idx + 1]
        payload = adv_data[idx + 2 : idx + 1 + ad_len]
        if ad_type in (AD_TYPE_NAME_COMPLETE, AD_TYPE_NAME_SHORT):
            try:
                return payload.decode("utf-8").strip()
            except Exception:
                return "Unreadable_Device"
        idx += ad_len + 1
    return "No_Name"

def ble_irq_callback(event, data):
    global dev_cache
    if event == _IRQ_SCAN_RESULT:
        _, _, _, _, adv_data = data
        dev_name = _parse_name(bytes(adv_data))
        now = time.ticks_ms()
        # 更新该设备最后活跃时间
        dev_cache[dev_name] = now

def start_background_full_scan():
    """启动后台永久高速扫描,匹配100ms间隔信标"""
    global SCAN_RUNNING
    if SCAN_RUNNING:
        return
    ble.active(True)
    ble.irq(ble_irq_callback)
    # gap_scan(永久扫描0, 扫描周期100000us=100ms, 监听窗口90000us=90ms, 主动扫描1)
    ble.gap_scan(0, 100000, 90000, 1)
    SCAN_RUNNING = True
    print("后台BLE扫描已启动 | 适配100ms间隔蓝牙信标")

def scan_ble_devices():
    """
    对外调用接口:瞬间返回当前在场蓝牙设备名称列表
    自动清理超时消失的设备,无阻塞
    return: list[str]
    """
    global dev_cache
    if not SCAN_RUNNING:
        return []
    now = time.ticks_ms()
    # 过滤超时设备
    valid_devs = []
    for name, last_tick in dev_cache.items():
        if time.ticks_diff(now, last_tick) < DEV_TIMEOUT:
            valid_devs.append(name)
    return valid_devs

def stop_ble_scan():
    """停止扫描、关闭蓝牙,程序结束时调用"""
    global SCAN_RUNNING
    if not SCAN_RUNNING:
        return
    ble.gap_scan(None)
    ble.active(False)
    SCAN_RUNNING = False
    dev_cache.clear()
    print("BLE扫描已关闭")

------------------- 测试示例 -------------------
if __name__ == "__main__":
    # 程序启动只执行一次,开启后台扫描
    start_background_full_scan()

    # 循环读取设备列表,随便高频调用无压力
    while True:
        dev_list = scan_ble_devices()
        print("==== 在场蓝牙设备 ====")
        if len(dev_list) == 0:
            print("无设备")
        else:
            for name in dev_list:
                print("-", name)
#         time.sleep_ms(500)

此条目发表在None分类目录。将固定链接加入收藏夹。

发表回复