ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

BLE蓝牙地址类型全解析与RPA自动化实战指南

BLE蓝牙地址类型全解析与RPA自动化实战指南 前阵子接了个批量验收蓝牙手环的项目两百多台设备要在几天内完成信号测试和数据回传。最开始我天真地以为用手机一台台去点配对就行结果第一天点了四十台眼睛就花了更别提中间还有十几台因为蓝牙地址重叠根本连不上。后来我索性把影刀RPA搭起来配合PC蓝牙栈做了套半自动巡检脚本才算把这事儿啃下来。也是在这个过程里我把BLE地址那套机制翻来覆去研究了个透——如果你要拿RPA去操控BLE设备地址这关绕不过去。这篇东西我会把两件事揉在一起讲透第一BLE的蓝牙地址到底有哪几种、每种是怎么回事、为什么有些设备换个地址你就连不上了第二RPA在BLE自动化场景里怎么落地、会遇到哪些坑、怎么排。内容面向的是正在做蓝牙设备产测、自动化巡检、或者想用RPA工具替代重复蓝牙操作的朋友懂一点Python更容易跟上不懂也能看懂原理。1. 先把连接这件事拆开广播、扫描、发起连接聊地址之前得先搞清楚地址在BLE连接过程里是干嘛用的。很多人把蓝牙连接想象成手机之间互加微信——知道ID就能发消息——但实际上BLE更像是在人群里喊话广播、听到、走过去搭话、建立稳定对话。整个过程分四步广播外设周期性把自己的存在感发出去广播包里除了设备名称、服务UUID还必带一个关键字段——自己的蓝牙地址。扫描主机手机、PC、RPA控制的蓝牙适配器在广播信道上监听把收到的广播包连同地址、RSSI信号强度一起报上来。发起连接主机挑一个目标地址发连接请求双方在数据信道上以约定的连接参数通信。配对绑定如果需要加密再走配对流程之后双方各存一份长期密钥下次见面直接认出彼此。蓝牙地址在整个流程里承担的是“身份标识”的角色但它这个身份标识跟IP不一样——IP地址在网络里也是可变的但好歹有个DHCP租约概念BLE地址更灵活有些地址变起来比换衣服还勤快。还有个常见误区蓝牙地址和Wi-Fi MAC地址虽然都长成XX:XX:XX:XX:XX:XX这个格式但它俩不是一回事。BLE的地址分公开地址和随机地址两大类随机地址里又分三种每种的行为逻辑都不一样。很多RPA脚本连不上设备问题就出在地址类型上——你以为设备地址是固定的结果它每隔几分钟换一次你的脚本傻乎乎地拿着旧地址去连当然失败。BLE工作在全球通用的2.4GHz ISM频段具体是2400MHz到2483.5MHz分成了40个信道其中37/38/39这三个信道专门做广播其余37个信道做数据传输。广播信道上挤满了各种设备的“叫卖声”扫描方就是靠地址字段区分谁是谁的。1.1 地址在连接参数里的“隐形作用”除了身份标识地址还会影响连接参数的协商过程。发起连接时主机发的CONNECT_REQ包里除了目标地址还带了一堆参数连接间隔connection interval、从机延迟slave latency、超时时间supervision timeout。从机收到后如果地址对得上、参数能接受就进入连接状态。这里有个很实际的经验用RPA做批量连接测试时连接间隔别设太短。我看到有人把连接间隔设成7.5msBLE允许的最小值结果RPA脚本里还没来得及处理上一批数据下一批就来了整个流程卡死。我自己的经验是连接间隔设在30ms到50ms之间配合slave latency设为4到8稳定性和功耗平衡得比较好。在自动化场景里稳定压倒一切极限参数留给实验室去跑。2. 蓝牙地址的四种身份从公开地址到私密地址BLE地址总共四大类下面这张表可以先存下来后面所有排查都靠它。地址类型名称是否固定能否被解析典型用途Public Address公开地址固定由IEEE分配能认证外设、工业设备Static Random Address静态随机地址上电随机但重启不变能大多数消费级手环、传感器Resolvable Private Address可解析私有地址RPA周期性轮换能需IRK密钥手机、耳机等防跟踪设备Non-Resolvable Private Address不可解析私有地址NRPA周期性轮换不能信标、匿名广播设备2.1 公开地址蓝牙世界的“实名制门牌号”公开地址是唯一需要花钱去IEEE申请前缀的格式上有个标志位区分。前24位是公司标识符OUI后24位是厂商自己分配的序号。这种地址出厂时烧死不能改就像门牌号一样——好处是稳定、好追查坏处是一旦泄露设备到哪儿都能被认出隐私性为零。实际产品里用公开地址的不多主要是成本问题。IEEE的OUI不是白给的小厂商不愿意花这个钱。而且工业场景里如果设备要出口公开地址还要走合规流程周期长。所以市面上绝大多数BLE设备用的是下面几种随机地址。2.2 静态随机地址消费级设备的“大众选择”静态随机地址虽然名字带“随机”但它其实没那么爱变。设备第一次上电时生成一个48位随机数最高两位设为1b表示静态随机类型然后把它存在非易失存储里之后每次开机都用同一个地址直到恢复出厂设置才会重新生成。这就好比你在小区里租了个固定停车位车牌号是随机选的但只要不搬家就一直是它。我手上的小米手环、某品牌的体脂秤用的都是静态随机地址。对RPA脚本来说这种地址最友好——设备重启后地址不变脚本里缓存一份地址就能长期复用。但要注意一个特殊场景有些设备做了“恢复出厂设置后地址重新随机”的逻辑如果RPA脚本批量测试时恰好有一台设备被人为重置过它的地址就变了脚本如果按旧地址去找必然扑空。所以在写RPA的时候建议不要只依赖地址过滤还要带上设备名称或者服务UUID双重校验。2.3 可解析私有地址手机和耳机的“隐私保护伞”可解析私有地址Resolvable Private Address是苹果、安卓手机和TWS耳机最常用的地址类型也是最让RPA头疼的一种。它的机制是这样的设备双方在绑定时交换一个叫IRKIdentity Resolving Key身份解析密钥的东西。之后设备每次广播或扫描都用这个IRK加上一个随机数算出一个新的地址隔一段时间就换一个。但换了又怎样持有对方IRK的设备收到地址后可以做一次“数学运算”把地址“解”开看是不是自己认识的那台设备。这就是“可解析”的含义——对认识你的人来说你换了马甲我也认得出对不认识你的人来说你每次都是个陌生人。用生活比喻就是你有个专属暗号你的朋友听到暗号就知道是你路人听到只觉得是噪音。RPA如果要连这类设备最正规的办法是先完成配对绑定拿到IRK之后无论地址怎么轮换系统蓝牙栈会自动识别。在Windows或者Linux上这个IRK存储在蓝牙协议栈里调用API连设备时不需要手动处理地址。如果你在RPA脚本里绕过系统蓝牙栈直接用hcitool这类底层工具去连拿到一个私有地址大概率会连失败——因为那个地址几秒钟后就失效了。2.4 不可解析私有地址彻底“匿名”的广播者NRPA这类地址最特殊它是随机生成的没有任何密钥能反推出设备身份而且可以频繁更换甚至每次广播都换一个地址。这等于一个人每次都戴着完全不同的面具上街连朋友都认不出来。它的用途通常是纯广播类的场景比如防追踪信标或者设备只想单向发数据、不想被别人连接。但RPA如果碰到用NRPA的设备几乎没办法稳定地去连接它——因为目标地址一直在变。这种场景下只能换个思路让广播包里带设备名称或其他标识RPA通过广播数据里的服务数据字段来识别目标而不是通过地址。3. 从设备上拿到真实地址日志、抓包和API返回讲完理论上实操。实际做RPA自动化时你得知道从哪儿拿到设备地址以及拿到的地址是不是能用来连接。3.1 Android和iOS隐私限制下的“变形地址”Android从6.0开始对蓝牙API做了隐私保护应用层在大多数情况下拿不到真实MAC地址BluetoothDevice.getAddress()返回的是固定的伪造地址02:00:00:00:00:00。你有BLUETOOTH_CONNECT权限也不行那是系统层面的限制。如果RPA跑在Android设备上别指望应用层能读到真实地址除非你的App是系统签名或者通过反射调用隐藏APIAndroid 8.0之后这条路也基本堵死了。实际可行的方案是用广播包里的RSSI和服务UUID来做匹配或者先触发配对流程在配对记录里通过系统数据库读到地址。iOS更绝CoreBluetooth根本不暴露MAC地址所有设备只有一个系统内部生成的UUIDidentifierForVendor之类。这个UUID每台手机每次都不一样而且是加密哈希出来的不是蓝牙地址。很多做uni-app开发的朋友问“iOS能不能根据蓝牙deviceid建立连接”——答案是可以建立连接但那个deviceid是iOS系统对BLE设备的抽象标识不是传统意义上的蓝牙MAC它只在当前设备上有效。同一台BLE设备在不同iPhone上看到的deviceid是不同字符串。安卓的情况又好一点OEM厂商的实现不完全一样有些国产ROM通过系统接口能拿到真实地址。不过在写RPA脚本时我建议按“拿不到真实MAC”来做设计能拿到算惊喜拿不到也不至于整个流程崩掉。下面表格总结了各平台情况平台应用层能否获取真实MACRPA可用的设备标识Android 6多数拿不到返回伪造地址广播包全局ID / 配对记录iOS拿不到CoreBluetooth 系统UUIDLinux能hcitool lescan / btmon完整MAC地址Windows视驱动和WinRT API而定部分可拿BluetoothAddressmacOS受限IOBluetoothDevice 的 MAC 字符串但老的API3.2 Linux下用hcitool和btmon抓真实地址Linux是做RPABLE自动化的最佳平台没有之一。原因很简单bluez协议栈对底层工具的访问几乎没有限制你可以看得清清楚楚。扫描周围设备sudo hcitool lescan输出类似LE Scan Report from: 00:1A:7D:DA:71:13 (public) Device: F4:5C:89:93:53:24 (random) Device: C4:7C:8D:6B:1A:02 (random) ...注意后面括号里的(public)和(random)这个信息太重要了——它直接告诉你目标设备用的是公开地址还是随机地址。如果是随机地址还可以继续分析是静态随机还是可解析私有地址。hcitool lescan在低功耗蓝牙上是扫描模式能看到广播包里的完整信息对于产测来说够用了。想看更细的广播数据和地址类型用btmonsudo btmon sudo hcitool lescanbtmon会把HCI层的所有事件打出来包括广播包的 AdvA广播地址、AdvData广播数据、RSSI等字段。我排查一个凌晨两点断连的问题时就是靠btmon抓到的广播包发现设备在某个固件版本上把地址类型从静态随机切成了NRPA导致主机侧一直认为“设备消失了”。还有hcidump老一些但也能用以及bluetoothctlbluetoothctl [bluetooth]# scan on [bluetooth]# devices3.3 抓包工具和App辅助定位nRF Connect这个AppAndroid/iOS都有是排查BLE问题的一把好手扫描页面会直接显示设备的地址类型和广播数据。我习惯用它在现场快速确认设备当前广播的是什么类型的地址然后再回到RPA脚本里去对齐逻辑。PC端还有Wireshark配合蓝牙适配器做被动嗅探但操作成本高一般产线不太用。日常RPA调试nRF Connect Linux命令行基本能覆盖90%的场景。4. ESP32轻度睡眠下的地址行为与低功耗权衡聊完怎么拿地址再看设备端。ESP32是RPA自动化里最常见的被测设备之一它的BLE实现在低功耗模式下的地址行为对自动化测试脚本的影响很大。ESP32轻度睡眠light sleep模式下CPU暂停但BLE外设可以继续工作广播和连接扫描都还能维持。此时地址的行为取决于固件里配置的地址类型使用静态随机地址从轻度睡眠唤醒后地址不变RPA脚本重连成功率极高但设备长期用一个地址有被跟踪的风险。使用可解析私有地址或NRPA设备每次广播周期都可能换地址功耗理论上更优隐私增强没有一成不变的身份暴露但RPA脚本如果按地址缓存去重连就会扑空。实测了一个场景某款ESP32传感器用静态随机地址广播间隔100ms轻度睡眠下平均电流约120μA如果改成每10分钟轮换一次NRPA平均电流几乎没变化但RPA侧识别设备的逻辑必须从“按地址过滤”改成“按名称服务UUID过滤”。换句话说隐私和功耗换来的是自动化的“模糊”——你要用更复杂的匹配逻辑去补偿。另外很多网友问“魔方蓝牙MAC地址怎么设置”实际上指的就是在ESP32或者类似模组固件里配置own_addr_type// 设置静态随机地址 esp_ble_gap_set_rand_addr(static_rand_addr); // 使用可解析私有地址 esp_ble_gap_config_privacy(true);这个设置同时也决定了RPA侧要如何去寻址。如果你的自动化目标是长期稳定地连同一台设备那就别开启隐私地址轮换如果设备本身就是要匿名广播的那就让RPA去广播包里找“人”而不是找“门牌号”。4.1 批量模拟多设备让RPA测试更像“产线”RPA做产测的时候有个需求模拟几十个设备同时广播看看主控能不能正确区分。我在ESP32上就是这么干的——让每个设备用不同的静态随机地址启动启动时通过配置接口烧录一个带有“设备编号”的广播数据。后面的RPA脚本按编号去匹配而不是按MAC匹配因为同一片模组重新刷固件后静态随机地址可能重新生成但设备编号会一直保留在NVS里。这种设计能避免产线上“MAC地址漂移导致数据对不上”的悲剧。5. RPA和BLE怎么才能真正打配合前面铺垫了这么多地址的底层机制现在说落地。RPA工具我主要用影刀金智维、Ui.Vision也试过本身不能直接操作蓝牙协议栈它靠的是“借壳生蛋”的思路。5.1 三种落地架构架构适用场景优点缺点GUI自动化 官方蓝牙App少量设备调试、手工流程替代开发量小上手快速度慢窗口焦点容易丢RPA调用CLI工具批量扫描、产测、数据采集速度快可脚本化所见即所得需要懂命令行和协议栈RPA 蓝牙网关/串口网关远距离、多设备、跨平台管理不受PC蓝牙栈限制可集中管控需要额外硬件成本我常用的是第二种RPA负责流程编排Excel读取、判断、报告生成Python脚本负责和蓝牙协议栈交互RPA通过命令行调用Python脚本并读取输出。5.2 一个典型的RPABLE流程场景批量读取50台设备的信号强度和设备信息结果写入Excel并生成报告。流程如下RPA从Excel读取待测设备清单含设备编号和预期地址/名称。RPA调用Python脚本执行hcitool lescan获取当前广播设备列表。Python脚本把广播结果解析成JSON设备地址、地址类型、RSSI、设备名称输出到临时文件。RPA读取JSON与Excel清单按设备名称或编号做匹配标记“发现/未发现”。对发现的设备RPA再调用Python脚本发起连接测试尝试读取GATT服务。结果回填Excel异常设备单独标记由人工复查。下面是那个Python脚本的核心片段我用的是bleak这个库比传统的bluepy在Linux上部署省心import asyncio from bleak import BleakScanner async def scan(): devices {} def callback(device, adv_data): # device.address 就是蓝牙地址 # adv_data.local_name 是设备名称可能为空 # adv_data.rssi 是信号强度 entry { address: device.address, name: adv_data.local_name or , rssi: adv_data.rssi, service_uuids: [str(u) for u in adv_data.service_uuids] } devices[device.address] entry scanner BleakScanner(detection_callbackcallback) await scanner.start() await asyncio.sleep(5) # 扫描5秒 await scanner.stop() return list(devices.values()) if __name__ __main__: result asyncio.run(scan()) import json print(json.dumps(result, ensure_asciiFalse))RPA那边就很简单了——用“执行命令行”组件跑这个脚本再读取标准输出里打印的JSON。用影刀的话可以直接用“Python脚本”组件也可以把脚本做成exe后调用看个人习惯。选型理由为什么选bleak而不是bluepy主要是Python3.10以上版本的兼容性bluepy依赖BlueZ的旧接口在某些新内核上编译报错bleak是纯Python封装、跨平台Windows/Linux/macOS都能跑。如果你的环境是Ubuntu 20.04 Python3.8bluepy还能凑合用但现在新项目我不推荐了。5.3 RPA脚本的“万能胶”设计RPA和脚本之间的数据对接是门学问。我的经验是所有中间数据一律走JSON并且打印到标准输出RPA从标准输出读取不要让Python脚本自己去写数据库或者发微信——那会让整个流程不好排查。影刀读取命令行输出没问题金智维也支持类似机制。如果数据量大可以写成临时CSV/JSON文件RPA再去读文件流程更清晰。这个“万能胶”设计还有个好处换RPA工具的时候只需要改一小段调用组件的配置核心蓝牙逻辑完全不用动。6. 实际跑自动化时最容易翻车的三个坑6.1 系统蓝牙栈“记住”了过期地址这是最常见的翻车点。Windows或者Linux的蓝牙栈会自动缓存曾经连接过的设备包括它们的地址、名称、IRK。当RPA脚本调用API去连接一个设备时系统可能会返回缓存里的信息而不是最新的广播地址。我遇到过的情况是这样的设备A原来用的是静态随机地址比如F4:5C:89:93:53:24后来固件升级改成NRPA轮换系统缓存里还留着那个旧地址和旧配对信息。RPA脚本用名字过滤去连接设备结果系统去连那个已经不存在的老地址一直报错。排查链路是先手动跑hcitool lescan发现设备A现在广播的地址已经变成了D3:21:5E:88:0A:77。bluetoothctl devices看系统缓存发现还是老地址。清缓存步骤bluetoothctl [bluetooth]# remove F4:5C:89:93:53:24 [bluetooth]# scan on重新扫描后缓存更新RPA流程恢复正常。在RPA流程里建议每个测试周期开始前加一次“清缓存/重新扫描”的步骤尤其是大批量产测的时候。用影刀的话可以在流程里加一个“执行bat脚本”的组件先把缓存清了再跑蓝牙脚本。6.2 私有地址轮换导致白名单失效有朋友做了一款儿童手表手表端用的是可解析私有地址RPA类型MCU里配置了白名单过滤只允许已知地址连接。原来用固定地址测试一切正常改成RPA类型后手机每次都连不上。根因是白名单过滤地址但地址在轮换白名单里的地址永远是旧的。正确做法是先用IRK做身份解析再决定是否允许连接——也就是“认人”而不是“认门牌号”。RPA脚本侧对应的问题就是你拿设备上次广播的地址去连接但这次设备已经换了新地址你的连接请求到达设备时设备比对地址发现“我不认识你”。排查方法是看设备端日志里面会打印“address resolution failed”之类的关键字说明IRK对不上或者还没完成配对绑定。解决办法先走近配对流程让双方完成IRK交换之后所有地址轮换都由蓝牙栈自动处理。RPA脚本只需要保证在发起连接前目标设备已经处于“已绑定”状态。6.3 RPA脚本的等待时间不够 连接超时处理不当BLE连接不是TCP那种“秒连”。广播间隔100ms、扫描窗口30ms的情况下从发起扫描到发现目标设备平均要花一两秒连接建立过程还要再花几百毫秒到几秒。RPA流程如果沿用网页自动化里的“马上执行下一步”逻辑几乎必挂。我踩过最蠢的坑脚本里连了5秒就报“未发现设备”后来手动扫描时发现设备其实就在旁边只是广播间隔被设置成了1000ms为了省电扫描周期不够长。正确做法是在RPA流程里加入统一的重试机制FOR attempt IN 1..3: 执行扫描等待N秒N根据广播间隔动态调整广播间隔100ms的等3秒1000ms的等10秒 如果发现目标设备 执行连接请求 IF 连接状态 成功: 读取服务退出循环 ELSE: 记录失败原因等待2秒继续下一次尝试 ELSE: 记录“未扫描到设备”继续下一次尝试 END FOR把这个逻辑用Python脚本实现RPA只负责驱动不要用RPA自身的“延时”组件去硬等那样流程图会乱成一团。6.4 完整排查链路案例最后放一个完整的排查案例方便你以后按这个路子走现象RPA脚本批量巡检时第13号设备在连续三轮巡检中有一轮能连上、两轮连不上日志里客户端报“GATT连接失败”。排查步骤手动打开nRF Connect扫描观察13号设备广播发现它的地址类型是resolvable private地址每2分钟轮换一次。用btmon抓连接过程发现RPA脚本发起连接用的地址是被缓存的旧地址设备端返回连接拒绝。检查RPA脚本逻辑发现里面写了“如果睡眠超过1分钟使用上次缓存的地址重新连接”而缓存地址在轮换后已经失效。修正改为每次连接前重新扫描并实时获取最新地址如设备已绑定则让协议栈自行解析IRK。连续跑5轮全部通过。排查链路的核心一句话先分清是“看不见”还是“连不上”。看不见是扫描/广播层问题连不上是连接参数/地址/配对问题。分错方向排查会绕很远。7. BLE Mesh与RPA地址从“点对点”走向“组网”前面聊的都是单点连接。如果你碰到的是Mesh组网场景智能灯、楼宇自动化地址机制又会再加一层复杂度同时RPA也能在配网和巡检上发挥大作用。BLE Mesh里节点不再只有一个地址而是有好几个单播地址unicast、组播地址group、虚拟地址virtual。配网器Provisioner在给设备配网时会从地址池里分配一个单播地址同时可以订阅/发布到不同的组播地址上。Mesh里的单播地址是配网器给的跟MAC没直接关系但底层蓝牙连接还是得靠MAC地址来建链。RPA可以做的是“批量配网自动化”RPA控制主机的蓝牙栈扫描未配网设备按设备编号分配地址、下发网络密钥、配置组播订阅。整个过程如果手工做一台设备半分钟一百台就得五十分钟用RPA编排配网脚本把每台设备的地址分配记录、网络密钥、订阅关系都写进Excel整体时间能压到十分钟以内。另外热词里提到的“ble mesh remote provisioning”是Mesh 1.1规范里新增的远程配网能力——配网器可以不和设备直接建立蓝牙连接而是通过一个已经在网的中继节点去给远处的新节点配网。这相当于“远程拉线”。对RPA的好处很明显配网人员不用跑现场去靠近每一台设备RPA只要控制一个中心节点就能批量搞定一整片区域的新设备入网。结合RPA实战时一个简单的做法是让RPA定期触发远程配网请求检查新节点的单播地址分配情况再把新节点加入某个组播地址。比如每天凌晨3点执行一次“发现新节点→分配地址→加入会议室灯组→验证状态→写入台账”的流程早上人来上班灯就能用。Mesh场景下RPA脚本要注意的是地址分配记录一定要持久化否则配网器重启后可能重新分配地址导致节点通信错乱。我在项目里有一个SQLite表专门存“设备编号 ↔ 单播地址 ↔ 组播地址 ↔ 网络密钥索引”RPA每完成一轮配网就更新一次再用Excel同步出来给人看。8. 最后的一点经验做RPABLE自动化的核心不是学RPA组件怎么拖拽而是先把蓝牙地址机制吃透。地址是设备和外界对话的“身份证明”你在RPA里写的每一个过滤条件、每一次连接请求都在跟这个身份证明打交道。不理解地址类型你连设备偶尔连不上这种问题的排查方向都找不对。有几条实在的经验送给准备上手的人先小规模跑通再放大。别一上来就搞两百台先用五台设备把地址识别、连接、数据读取、异常重试整个链路跑通再往大了扩。RPA脚本在高并发扫描的时候PC蓝牙栈本身可能先撑不住同一时间只能有一个进程用HCI所以产线方案通常是用多台树莓派做分布式扫描RPA统一调度。测试前先手工记录一批设备的地址类型。用nRF Connect或者hcitool看一眼知道目标设备用的是静态随机还是可解析私有地址后面写RPA逻辑能少踩一半坑。日志要打全。RPA脚本里每一步的输入输出都打印出来尤其是扫描结果、连接状态、GATT读写返回。错误信息写明白出问题十分钟就能定位不写日志的话光是复现问题就可能花一个下午。给RPA脚本加“人味”再自动化的流程也要保留人工介入的入口比如异常设备单列、关键节点暂停确认、批次结果人工抽查。我在产测项目里都是让RPA跑完自动生成一份汇总表然后我肉眼扫一眼再放行——省事的同时心里踏实。最后分享个小技巧BLE自动化的验收标准里加一个“地址轮换稳定性测试”让设备在测试期间周期性更换地址RPA脚本要保证每次都能通过IRK或名称正确识别并连接。这条通过了你的RPA流程在真实世界里才站得住脚。
返回列表