4、监督超时设置:连接丢失检测的时间窗口,如何平衡安全性与功耗
监督超时(Supervision Timeout),说白了就是蓝牙连接断开的「最后通牒」。
我习惯把它比作一个倒计时闹钟。连接建立后,主从双方每隔一段时间就得交换一次「我还活着」的信号。如果闹钟响了还没收到信号,系统就判定连接丢失,直接断开。
这个时间窗口设多长,直接决定了你的设备是「反应灵敏」还是「省电至上」。嗯,这里面的门道不少。
4.1 监督超时的底层逻辑
先看协议栈里怎么定义的。在蓝牙 Core Spec 中,监督超时是一个 16 位的值,单位是 10ms。取值范围从 100ms 到 32 秒。
// 监督超时配置示例
// 单位:10ms,范围:0x000A (100ms) 到 0x0C80 (32s)
#define SUPERVISION_TIMEOUT_MS 2000 // 2秒
uint16_t timeout_raw = SUPERVISION_TIMEOUT_MS / 10; // 得到 200
但要注意,这个值不能随便设。它和连接间隔(Connection Interval)有严格的数学关系:
核心约束:
监督超时 > (1 + latency) × connectionInterval × 2
说白了,超时时间至少要能覆盖两个完整的连接事件周期。
为什么?我举个例子。假设连接间隔是 30ms,从机延迟(Slave Latency)设了 4 个。那么最坏情况下,从机可以连续跳过 4 个连接事件,也就是 120ms 不回复。如果监督超时设成 150ms,那刚好够用。但要是设成 100ms,连接就会频繁误断。
我在项目中遇到过这种坑。有一次调试一个传感器节点,总是莫名其妙断开。查了半天,发现是监督超时设得太短,刚好卡在边界上。后来加了 20% 的余量,问题就解决了。
4.2 安全性:反应要快,但不能误判
安全性,说白了就是「连接断了要立刻知道」。这在很多场景下是刚需。
比如医疗设备、工业控制器、门锁。连接一断,系统必须马上进入安全状态。这时候监督超时就得设得短一些。
我个人习惯的做法是:
- 关键控制类设备:监督超时设在 500ms ~ 1s 之间。比如智能门锁,用户按了开锁键,如果连接断了没反应,体验极差。
- 数据采集类设备:可以放宽到 2s ~ 5s。比如温度传感器,丢几秒数据问题不大。
- 音频/流媒体设备:通常用 1s ~ 2s。太短了容易因为干扰而断连,太长了用户会感觉卡顿。
避坑指南:
我曾经把一个门锁产品的监督超时设成了 300ms。结果在电梯里测试时,因为信号反射干扰,连接频繁误断。用户反馈说「门锁疯了,老是自动断开」。后来改回 800ms,问题消失。
所以,安全性不是越短越好。要留出足够的抗干扰余量。
4.3 功耗:时间越长,越省电
功耗这块,道理很简单:监督超时越长,设备在连接丢失后「傻等」的时间就越长。但反过来,超时越长,设备越不需要频繁检查连接状态。
你想想看,如果监督超时设成 10 秒,那么从机可以在 10 秒内完全不理会主机,安心睡大觉。这对电池供电的设备来说,简直是福音。
具体来说:
- 短超时(< 1s):设备必须频繁唤醒,检查连接是否还在。功耗高,但响应快。
- 长超时(> 5s):设备可以深度睡眠,只在连接事件到来时醒一下。功耗低,但连接丢失后要等很久才能发现。
我做过一个对比测试。同样的传感器节点,监督超时从 1s 改成 5s,平均电流从 120μA 降到了 45μA。省了将近三分之二。代价是连接断开后,系统要等 5 秒才能反应过来。
4.4 平衡的艺术:一个实用的决策框架
怎么平衡?我总结了一个简单的决策流程:
- 先确定安全需求:连接丢失后,系统需要多快响应?1 秒?5 秒?10 秒?
- 再算功耗预算:电池能用多久?如果要求一年不换电池,超时就不能太短。
- 最后考虑环境干扰:设备在室内还是室外?有没有金属遮挡?干扰大的地方,超时要适当加长。
下面这个表格是我常用的参考值:
| 应用场景 | 连接间隔 (ms) | 从机延迟 | 监督超时 (s) | 典型功耗 |
|---|---|---|---|---|
| 智能门锁 | 30 | 0 | 1.0 | 中 |
| 心率胸带 | 50 | 4 | 3.0 | 低 |
| 温湿度传感器 | 100 | 9 | 5.0 | 极低 |
| 工业控制器 | 20 | 0 | 0.5 | 高 |
我的个人经验:
如果你不确定怎么设,先按「连接间隔 × (1 + 从机延迟) × 3」来算。这个公式给了足够的余量,既不会误断,也不会太耗电。等实际测试后,再根据情况微调。
4.5 动态调整:进阶玩法
有些场景下,固定一个超时值不够灵活。比如一个设备,平时在室内工作,偶尔拿到户外。室内干扰小,户外干扰大。
这时候可以考虑动态调整监督超时。协议栈允许在连接过程中修改这个参数,通过 L2CAP_ConnParamUpdateReq 或 LL_ConnectionUpdateReq 来实现。
// 动态调整监督超时的伪代码
if (rssi < -80) {
// 信号差,增加超时,防止误断
supervision_timeout = 3000; // 3秒
} else {
// 信号好,缩短超时,快速响应
supervision_timeout = 1000; // 1秒
}
// 发送连接参数更新请求
send_connection_update(interval, latency, supervision_timeout);
嗯,这里要注意。动态调整不是想改就能改的。主机端可能拒绝你的请求。所以最好在连接建立初期就协商好一个合理的范围。
我记得有一次做可穿戴设备,用户运动时信号波动很大。固定 2 秒超时,跑步时经常断连。后来改成根据加速度计数据动态调整:静止时用 1 秒,运动时用 3 秒。效果好了很多。
4.6 总结:记住这三条
好了,关于监督超时,我最后总结三条核心原则:
- 安全优先:关键应用,超时别超过 1 秒。但别忘了留余量。
- 功耗靠拖:想省电,就把超时拉长。配合从机延迟,效果更佳。
- 动态为王:如果环境多变,别死守一个值。动态调整才是最优解。
说白了,监督超时就是一个「你愿意等多久」的问题。等得短,反应快但费电;等得长,省电但迟钝。没有绝对正确的值,只有最适合你场景的值。
下一章,我会讲从机延迟的配置技巧。那个参数和超时配合好了,功耗能再降一个台阶。