本节摘要:把 WiFi 蓝牙这类无线栈当"能用的库"是原型思维;产品思维要把连接本身当成一台需要管理的小机器——它有状态、有耗时、有脾气。本节给出连接状态机的标准设计、各类无线操作的耗时预算,以及"偶发掉线后永久失联"这一经典故障的状态机修复实录。
第 5 章的数据已经备好,本章解决"送到哪里去"的问题。6.1 放在四层之底:链路不稳,上面三层全是空中楼阁。而管理链路的第一课,恰恰是承认自己管不了电磁波——能管的只有自己的状态机与重试策略。
原型代码里 WiFi 只有两个状态:连上了、没连上。产品的无线连接至少有六个状态:开机初始化、扫描、认证关联、获取地址、在线、退避重连。每个状态有自己的耗时量级与失败出口,缺一个状态,就少一种故障的处理路径。
先给耗时预算建个账(以 WiFi 为例,量级供参考):扫描全部信道 1 至 3 秒;认证关联数百毫秒;DHCP 获取地址半秒上下;TLS 握手在 MCU 上 1 至 4 秒(取决于加密硬件)。也就是说,一次完整的冷连接可能花掉 5 秒以上。这笔账直接决定两个设计:重连不该从扫描开始(已知路由器可跳过扫描省 3 秒);连接期间主业务不能被阻塞(扔进独立任务,第 4 章的任务划分在此兑现)。

"偶发掉线后永久失联"几乎都是同一个病灶:某一步失败后代码停在了原地等一个不会来的事件。常见三处——扫描函数永不返回(底层栈 Bug 或信道异常)、DHCP 拿不到地址又不超时、TLS 握手对端无响应干等。解法是给每个状态加看门狗式超时:进入状态时启动计时器,超过该状态耗时上限的十倍就强制打断,转入退避重连。
退避策略在支柱页已经预告:指数增长加随机抖动,上限五分钟。这里补一个细节——退避状态里不能闲着:本地业务(采集、缓存)照常运转,网络只是暂停。把"联网"设计成设备的附属功能而非生存条件,断网期间数据落盘、恢复后补传,产品力反而上了一个台阶。
背景:一批联网温控器投放到二十个门店,运行数天后零星出现"彻底失联":云端看不到设备,但现场看设备指示灯还在闪,重启才恢复。
操作:现场接串口抓日志,复现一次:路由器夜间重启,设备断线,日志显示"重连中"持续打印——但两小时后仍在打印同一句。分析日志时间线:首次重连扫描无果后进入重连逻辑,而代码的重连路径调用的是异步扫描启动函数,没有检查启动是否成功,也没有注册结果回调——扫描请求被底层队列丢弃后,状态机停在"等待扫描结果"再无人唤醒。修复:所有异步调用检查返回值;给"等待扫描"状态加 10 秒超时;超时进入退避重连。
结果:复现脚本(定时重启路由器)连跑 48 小时,设备全部在 2 分钟内恢复在线,无一失联。
解读:这起故障的三要素——异步调用不查返回值、等待无超时、状态无出口——是无线栈管理的三大惯犯。无线环境的不确定性不可消除,状态机的完备性才是设备与混乱环境的和解协议。写连接代码时做一件事:给状态机每个节点问一句"如果这一步永远不返回,谁会来救我?"答不上来的节点,就是下一个失联门店。
变式:蓝牙、LoRa、NB-IoT 等其他无线栈的状态机形态各异,但三条纪律普适:状态有出口、异步查返回、退避有上限。栈越慢(比如 NB-IoT 的附着注册可能十几秒),超时阈值越要按实测放宽,而不是照搬 WiFi 的秒级经验。
⚠️ 常见坑:把 WiFi 配置写成"扫描最强信号自动漫游"却不做信号质量评估,设备会在两个信号都差的边缘位置反复横跳——每跳一次就是一次完整冷连接。固定目标或按滞回逻辑切换,比"最强"聪明。
💡 关键直觉:无线栈的 API 多数是异步的,而异步代码的全部纪律浓缩成一句话:发出请求时就想好"如果它不理我怎么办"。想好这句话,90% 的失联 Bug 不会出生。
把 6.1 的耗时量级变成一张要自己填的表。拿真机与路由器,实测以下各项并记录:冷启动到扫描完成、已知网络跳过扫描的关联认证、DHCP 获取地址、TLS 握手(TCP 到应用可用)、以及断电恢复到完全在线的总时长。填完这张表,你会得到几个关键决策的依据:重连逻辑是否跳过扫描、心跳间隔取多长、以及断网恢复期间缓存要撑多久。
再把无线参数按场景对一遍:发射功率按最弱信号点留 10 分贝余量,而不是顶格设置——顶格功率既费电又可能违反本地法规;路由器的 DTIM 间隔决定深眠监听的唤醒频率,与云平台约定的心跳周期要对齐,否则"省电的监听"会被频繁的组播缓存打断。这张表加这一段参数,就是设备无线行为的产品规格——它应该进设计文档,而不是只活在工程师的记忆里。
WiFi 之外的无线栈各有脾气,但管理框架可以复用。蓝牙 BLE:连接由中心设备发起,设备侧要管理广播间隔——广播越频繁越易被发现,功耗也越高;连接参数(连接间隔、从机延迟)要与 App 端协商,默认参数往往不适合批量数据传输。NB-IoT 与 LTE 类:附着注册可能十几秒,状态机超时要整体放大一个数量级;PSM 与 eDRX 两种省电模式的唤醒粒度差异巨大,选错模式会让"上报一次、醒来半天"。LoRa 类:占空比受法规约束,发送策略本质是配额管理,重试逻辑要计入配额消耗。
把这些差异抽象一下:任何无线栈的管理都落在四个旋钮上——发现成本、连接耗时、心跳粒度、发送配额。WiFi 与 BLE 的旋钮值小而灵活,广域网的旋钮值大而受限。换栈时先重新填一遍这四个旋钮,状态机骨架不用动,6.1 的纪律原样生效。