11.3. 无线电与链路层¶
从 Python 的视角看,BLE 协议栈最底下的两层几乎完全是自动的——无线电芯片以及 MicroPython 运行其上的那些层,处理了从选择信道到重传丢失数据包的一切。它们所做的选择中,仍有三项会显现到面向用户的 API 中:功耗、范围和吞吐量。
11.3.1. 无线电¶
BLE 使用与 Wi-Fi、微波炉以及大多数其他短距离无线设备相同的 2.4 GHz 工业-科学-医疗(ISM)频段。该频段被划分为 40 个各 2 MHz 宽的信道。
40 个信道中的三个保留用于广播——向任何正在监听的设备宣告某设备存在的简短广播。它们在频段上彼此间隔较远,这样监听者可以快速扫过这三个信道,而且任一信道上的干扰也不太可能把设备完全挤出空中。
三十七个是数据信道。两台设备一旦连接,就在这些信道上交换数据包,按照双方在连接时约定好的伪随机序列在它们之间跳变。自适应跳频让任一方都能把某个信道标记为不良(严重的 Wi-Fi 干扰、微波炉、相邻的 BLE 网络),从而让序列跳过它。
2.4 GHz 频段上的 40 个 BLE 信道。三个用于广播,其余的在开放连接上承载流量。¶
无线电发送简短的数据包——最长不过几毫秒——并在其间休眠。正是这段休眠让该技术成为低能耗的。一个典型的 BLE 外设实际用于发送的时间远低于其全部时间的百分之一;其余时间里,无线电在两次计划事件之间处于断电状态。
11.3.2. 链路层¶
链路层是 BLE 中与另一台设备上的对应方对话的最小单元。它负责四项工作。
数据包分帧。每个数据包都带有一个简短的报头(信道接入地址、数据包长度、控制位)、一段载荷以及一个 CRC。接收方校验 CRC 并丢弃任何损坏的内容。
寻址。每台 BLE 设备都有一个 48 位的设备地址,用于在无线电上标识它。有些是公开的——制造商分配的硬件标识符,可被永久追踪。有些是随机的——在设备上生成、周期性轮换,并可选地加密,使得窃听者无法把两次传输关联到同一个物理硬件上。地址会在 广播与扫描 中再次出现。
连接调度。两台设备一旦连接,链路层就按跳频序列调度周期性的无线电事件——彼此相隔一个固定的连接间隔——并把上层 GATT 排队的任何数据打包进每一次事件。两端在事件之间都会回到休眠状态。连接间隔是应用可以请求的一个旋钮(参见 连接)。
可靠性。连接上的每个数据包都会被对方确认。链路层会重传任何未收到响应的内容,因此上层看到的是一条有序、无损的字节流。与网络一侧的 UDP —— 发出一个数据包,听天由命 不同,BLE 在正常使用中没有单独的不可靠模式——开放连接上的每个数据包都会一直重试,直到它送达或链路被判定丢失。
链路层也是加密运行的地方——一旦一对设备在配对期间约定了密钥(参见 配对与绑定)。加密链路上的每个数据包都会在接收端先被解密,上层才有机会看到它。
11.3.4. Python 对这一切看到了什么¶
几乎什么都看不到。bluetooth 和 aioble API 并不暴露信道、跳频序列、数据包 CRC 或重传定时器;这些全都在 BLE 端口和无线电内部处理。确实会显现出来的部分,是那些由连接时协商所暴露的——连接间隔、MTU、地址类型。