这里的“WiFi 指纹”不是 WiFi 密码,也不是简单判断“手机是否连接了某个 WiFi”,而是利用不同位置接收到的多个 AP 信号强度组合,推断设备所在的座位。
1. WiFi 指纹到底是什么
一个自习室通常有多个无线 AP。手机在不同座位上扫描到的 AP 信号强度不同。
例如,手机在座位 A 扫描得到:
AP_001: -42 dBm
AP_002: -67 dBm
AP_003: -75 dBm
AP_004: -89 dBm在座位 B 可能得到:
AP_001: -58 dBm
AP_002: -52 dBm
AP_003: -81 dBm
AP_004: -70 dBm虽然两个座位都连接同一个 WiFi,但各 AP 的信号强度组合不同。这个组合就像该位置的“无线指纹”。
可以表示为:
F = {
BSSID_001: -42,
BSSID_002: -67,
BSSID_003: -75,
BSSID_004: -89
}其中:
BSSID:某个 AP 的唯一标识;RSSI:手机接收到该 AP 的信号强度;- RSSI 通常是负数;
- 越接近 0,信号越强;
-42 dBm通常比-75 dBm强。
不能只记录 WiFi 名称 SSID,因为多个 AP 可能使用同一个 SSID。应优先使用 BSSID 作为特征标识。
2. 它是如何定位座位的
WiFi 指纹定位不是通过公式直接计算距离,而是一个“采集样本、建立数据库、进行匹配”的过程。
第一步:建立指纹库
提前在每个座位采集大量样本。
例如:
| 座位 | AP_001 | AP_002 | AP_003 | 采集时间 |
|---|---|---|---|---|
| A-01 | -42 | -67 | -75 | 上午 |
| A-01 | -45 | -65 | -77 | 上午 |
| A-01 | -41 | -70 | -73 | 下午 |
| A-02 | -58 | -52 | -81 | 上午 |
| A-02 | -61 | -50 | -79 | 下午 |
同一个座位不会只有一条指纹,而是会有一组指纹,因为 WiFi 信号会波动。
第二步:用户现场采集
用户进入自习室后,Android 客户端扫描当前环境:
当前观测:
AP_001: -44
AP_002: -68
AP_003: -76第三步:和指纹库匹配
系统把当前观测与所有座位的历史指纹进行比较。
如果当前数据与 A-01 的样本最接近,则认为用户可能位于 A-01。
3. 为什么不能只看一个 AP
如果只使用一个 AP 的 RSSI,会出现很多问题:
- 相邻座位信号差异很小;
- 手机方向变化会影响 RSSI;
- 人体、桌椅、墙壁会造成遮挡;
- 某个 AP 可能暂时拥塞或失效;
- 5 GHz 和 2.4 GHz 的传播特性不同。
因此需要使用多个 AP 的组合:
[AP_001, AP_002, AP_003, AP_004, ...]通常 AP 越多、空间分布越合理,座位之间越容易区分。但 AP 数量不是越多越好,过弱、经常消失或变化很大的 AP 可能增加噪声。
4. 指纹数据如何预处理
原文档中提到的预处理主要解决三个问题:缺失、波动和设备差异。
4.1 AP 对齐
不同手机扫描到的 AP 集合可能不完全一样,所以要建立统一的 AP 列表:
AP_001, AP_002, AP_003, AP_004如果某次扫描没有发现 AP_003,就需要补一个特殊值,例如:
AP_003 = -100这里的 -100 不是实际测得的 RSSI,而是“没有检测到”的标记。实际实现时也可以额外增加一个“是否检测到”的字段,避免把缺失误认为真实弱信号。
4.2 去除异常值
例如某个 AP 平时在 -60 到 -75 之间,突然出现 -20 或 -110,就需要检查:
- 是否扫描异常;
- 是否 AP 发生切换;
- 是否数据解析错误;
- 是否设备靠近 AP;
- 是否环境突然变化。
4.3 平滑处理
连续采样可能是:
-61, -65, -59, -70, -63可以使用中位数:
-63也可以使用移动平均或指数平滑,减少瞬时波动。
不过中位数、移动平均、指数平滑不一定全部叠加使用,应通过实验比较哪种效果最好。
4.4 设备差异校准
不同手机的 WiFi 芯片和天线不同。同一个位置上:
- 手机 A 可能测到
-60; - 手机 B 可能测到
-67; - 手机 C 可能测到
-55。
因此采集指纹库时不能只使用一部手机。至少应使用 2 至 3 种 Android 设备进行测试,并分别统计准确率。
5. KNN 如何匹配座位
KNN 的基本思想是:
当前观测和哪些历史样本最接近,就把当前设备判定到这些样本所属的座位。
假设当前向量是:
X = [-44, -68, -76, -88]某个历史样本是:
Y = [-42, -67, -75, -89]可以计算它们的距离:
distance = sqrt(
(-44 + 42)^2 +
(-68 + 67)^2 +
(-76 + 75)^2 +
(-88 + 89)^2
)距离越小,说明两个指纹越相似。
加权 KNN 会让距离更近的样本拥有更高权重:
权重 = 1 / (距离 + ε)最后统计最近的若干个样本属于哪个座位。
输出可以是:
{
"top1Seat": "A-01",
"candidates": [
{"seat": "A-01", "score": 0.86},
{"seat": "A-02", "score": 0.63},
{"seat": "B-01", "score": 0.41}
],
"confidence": 0.86,
"needManualReview": false
}这里的 confidence 不是严格意义上的概率,而是一个用于比较和决策的可信度分数。必须在实验中进行校准,不能直接把 0.86 宣称成 86% 的真实准确率。
6. 为什么需要 Top-3,而不是只给一个座位
相邻座位的 WiFi 指纹可能非常接近。例如 A-01 和 A-02 只相差几十厘米,RSSI 变化可能小于环境噪声。
所以系统最好返回:
最可能:A-01
候选:A-02、A-03这样可以:
- 为推荐系统提供多个备选;
- 在可信度低时提示用户确认;
- 让管理员查看算法混淆情况;
- 避免系统把一个不确定结果伪装成绝对正确。
7. WiFi 指纹能不能直接判断“人是否在座位上”
这是项目中最容易被误解的部分。
WiFi 指纹主要能判断:
某个设备当前更可能位于哪个位置。
它不能直接证明:
设备的主人此时正在座位上。
例如:
- 用户把手机留在座位上,人已经离开;
- 用户带着手机离开,但电脑仍然连接 WiFi;
- 手机进入省电模式,暂时没有扫描;
- 用户坐在座位旁边,信号被判定到相邻座位;
- 多个人的设备同时影响无线环境。
因此,占座检测不能只依赖一次 WiFi 指纹,而应结合:
- 用户主动开始使用;
- 用户主动释放;
- 连续多次定位结果;
- 设备信号是否持续;
- 离开持续时间;
- 使用时长;
- 设备是否在多个座位间快速跳转;
- 管理员人工复核;
- 可选的路由器连接日志。
正确的结果应该是:
设备疑似位于 A-01
→ 连续多次稳定检测
→ 判断 A-01 正在使用
→ 长时间出现异常行为
→ 标记为疑似占座
→ 管理员复核不能写成:
检测到 WiFi 设备
→ 直接确定有人占座8. 推荐的占用状态流程
可以使用以下状态机:
空闲
↓ 检测到设备
疑似使用
↓ 连续多次确认
使用中
↓ 信号短暂消失
疑似离开
├─ 短时间内恢复 → 使用中
└─ 超过离开阈值 → 空闲疑似占座流程:
使用中
↓ 长时间异常
疑似占座
↓ 管理员复核
正常使用 / 空闲例如:
- 连续两次识别到同一座位:进入“疑似使用”;
- 连续 2 至 3 次结果稳定:进入“使用中”;
- 信号消失 1 至 3 分钟:进入“疑似离开”;
- 超过 10 分钟没有恢复:释放座位;
- 设备仍存在但用户行为异常超过 30 至 60 分钟:标记“疑似占座”。
这些时间只是初始参数,最终必须用现场数据调整。
9. 采集指纹时应该怎么做
每个座位不能只采集一次,建议:
- 每个座位每个时段采集 5 至 10 次;
- 至少采集早、中、晚三个时间段;
- 覆盖工作日和周末;
- 使用 2 至 3 种 Android 手机;
- 记录手机型号;
- 记录采集方向和持握高度;
- 记录是否有人、门窗是否打开、附近是否有遮挡;
- 采集相邻座位和通道位置作为对照。
一个采集样本应包含:
{
"roomId": 1,
"seatId": "A-01",
"deviceModel": "Pixel-6",
"sampleTime": "2026-10-01T09:30:00",
"wifi": [
{"bssid": "AP_001", "rssi": -44, "frequency": 5180},
{"bssid": "AP_002", "rssi": -68, "frequency": 2412}
],
"environment": "上午,人流较少"
}10. Android 端和路由器日志的区别
这里需要特别修正文档中的一个技术边界。
Android 主动扫描
Android 手机自己扫描周围 AP,得到:
多个 BSSID + 多个 RSSI这最适合做 WiFi 指纹定位,也是本项目第一版推荐的方式。
路由器日志
路由器通常能提供:
- 哪个设备连接了哪个 AP;
- 设备连接和断开时间;
- 有些设备能提供客户端 RSSI;
- 部分企业级 AP 控制器能提供更多定位信息。
但普通路由器日志通常不能直接提供一组完整的“房间空间指纹”。因此:
路由器日志适合辅助判断设备是否在线,不应默认当作完整的 WiFi 指纹定位数据。
推荐采用混合方案:
Android 扫描结果
负责座位级定位
路由器连接日志
负责辅助判断设备在线和离线
用户操作
负责建立使用意图
管理员复核
负责处理疑难情况11. 最适合本项目的实际方案
我建议第一版采用:
- Android 采集端在每个座位建立指纹库;
- Android 用户端在用户明确进入使用状态后进行受控扫描;
- 扫描结果上传后端;
- Python 服务使用加权 KNN 推断候选座位;
- Spring Boot 根据连续结果更新座位状态;
- 路由器日志只作为辅助信号;
- 低可信度和异常状态进入管理员复核;
- 所有判断保留原始事件、特征摘要和模型版本。
需要注意的是,Android 后台 WiFi 扫描受系统限制。不能假设应用被切到后台后仍然可以无限制稳定扫描,所以产品上应提供:
- 前台采样服务;
- 明确的采样状态;
- 采样失败提示;
- 手动刷新;
- 网络断开重试;
- 无法定位时的人工确认。
12. 应该如何评价 WiFi 指纹效果
不能只说“定位准确”,需要具体测量:
- Top-1 准确率:第一候选就是正确座位的比例;
- Top-3 准确率:前三个候选包含正确座位的比例;
- 相邻座位混淆率;
- 不同手机型号的准确率;
- 不同时间段的准确率;
- 有人和无人环境下的准确率;
- AP 故障时的准确率;
- 平均状态更新时间;
- 正常离开被误判为占座的比例;
- 真正占座没有被发现的比例。
数据划分不能把同一轮采样的相邻数据随机打散到训练集和测试集,否则结果可能虚高。应按日期、采集设备或采集批次划分测试数据。
13. 最重要的结论
WiFi 指纹在这个项目中适合解决:
“这个设备更可能位于哪个座位?”
它不适合单独解决:
“这个人是否一直坐在这个座位上?”
所以完整系统应该是:
WiFi 指纹定位
+ 连续时间行为
+ 用户使用会话
+ 路由器在线信息
+ 管理员人工复核这样才能把“座位定位”和“占座检测”区分开,避免项目答辩时被质疑技术结论过度夸大。原开发文档中的算法部分基本方向正确,但“路由器日志可以直接参与完整指纹定位”这一点需要改成“Android 主动扫描负责指纹定位,路由器日志作为辅助数据”。