news 2026/7/14 14:28:56

那些藏在墙角里的“听风者”——一个WiFi探针系统的技术自白

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
那些藏在墙角里的“听风者”——一个WiFi探针系统的技术自白

大家好,我叫“WiFi探针系统”。别被这名字唬住,其实我就是四个指甲盖大小的ESP8266电路板,分别蹲在XX大学图书馆的四个角落里,干着一件特别“八卦”的事情——偷听手机们的悄悄话

我知道你肯定会问:手机们能有什么悄悄话?嘿,多了去了。你每打开一次WiFi开关,你的手机就像个找不到家的孩子,嗷嗷喊着“有WiFi吗?有WiFi吗?”——这句喊话在802.11协议里有个正经名字,叫Probe Request帧。而我干的事情,就是把这些喊话记下来:谁喊的(MAC地址)、喊多大声(RSSI信号强度)、朝谁喊的(BSSID目标地址)。

就这么简单?对,就这么简单。但要把这点简单的事儿干利索,背后的故事可不少。

一、硬件篇:一个“穷鬼”的自我修养

先说说我的“身体”吧。四个ESP8266 ESP01S模块,单价不到15块钱。有人可能会撇嘴:这么便宜能靠谱吗?

说实话,确实不太靠谱。

首先,这玩意儿内存只有80KB。80KB是什么概念?你手机里随便一张照片都比它大几十倍。就这么点内存,我还要同时干两件事:一是开着混杂模式抓包——说白了就是把耳朵竖起来听所有经过的WiFi信号,不管是不是喊给我的;二是连上WiFi把数据传到服务器。

问题来了:ESP8266在混杂模式下没法连WiFi。这不是bug,是硬件层面的“生理缺陷”——就像你不能同时吃饭和唱歌一样。

怎么办?我们设计了一套“轮班制”:

采集30秒 → 关掉混杂模式 → 连上WiFi → 把攒的20条数据发出去 → 断开WiFi → 重新开混杂模式

整个过程像极了打工人的日常:埋头干活(采集)→ 抬头交差(发送)→ 再埋头干活。一个循环大概35秒,数据延迟就这么来的。没办法,穷有穷的活法。

二、数据篇:33个字节的“极限压缩”

攒下来的数据怎么传?我们没选JSON——那玩意儿虽然人类看得懂,但太啰嗦了。一条记录动不动上百字节,对于我这种每次只能连几分钟WiFi的“穷鬼”来说,太奢侈了。

我们设计了一个33字节的二进制协议。来,我给你拆开看看:

位置内容大小说明
第0字节RSSI1字节信号强度,负值,越大表示离得越近
第1-6字节MAC地址6字节设备的“身份证号”
第7-12字节BSSID6字节目标AP地址,全F表示设备在“广播式扫描”
第13-16字节时间戳4字节Unix时间,精确到秒
第17字节信道1字节当前WiFi信道(1-13)
第20字节估算距离1字节根据RSSI粗算的距离
第25字节连接状态1字节0=扫描中,1=已连接

33个字节,把该记的都记了。你说这算不算“螺蛳壳里做道场”?

对了,这里有个特别有意思的细节——BSSID字段。如果BSSID是FF:FF:FF:FF:FF:FF,说明设备正在“广播式扫描”,也就是还没连上任何WiFi,像个无头苍蝇一样到处问“谁家有网”。如果BSSID是个具体的MAC地址,说明设备已经连上某个AP了,只是偶尔还发个探测帧刷存在感。

这个区别很重要。因为已连接设备用的往往是真实MAC地址,而那些还在扫描的设备,很可能用了随机MAC——这事儿我们后面再聊。

三、信道篇:一个“陀螺”的自我修养

WiFi有13个信道,手机可能在任何信道上喊话。我只有一双耳朵,一次只能听一个信道。怎么办?

轮巡。每500毫秒切一次信道,1→2→3→...→13→1→2→...像个不知疲倦的陀螺。

这方法笨,但有效。不过也有翻车的时候——高峰期某些信道流量特别大,500毫秒根本不够用,数据就丢了。后来我们改成了“流量自适应”:某个信道如果连续几次都抓不到东西,就少待会儿;反之就多待会儿。效果嘛,提升了大概5%的捕获率——折腾了好几天,就提了5%。写论文的时候我就在想:这事儿到底值不值得写?后来想通了,“做了但效果一般”也是经验,总比假装没做过强。

四、定位篇:加权质心的“算术魔法”

好,数据有了——四个节点分别报告了某个设备的RSSI值。接下来就是算位置了。

我们用了一个叫加权质心的算法。名字听着唬人,原理特别简单:

把每个节点的RSSI换算成“权重”,信号越强权重越大,然后拿四个节点的坐标做加权平均。

公式长这样:

P = Σ(w_i × P_i) / Σ(w_i)

其中w_i = 10^(RSSI_i / 10),就是把dBm换算成毫瓦。

说白了就是:谁的信号强,设备就大概率在谁附近

这法子简单粗暴,但也有硬伤——RSSI太不靠谱了。你站在同一个地方不动,RSSI能上下波动10个dBm。为什么?因为人走来走去会遮挡信号,墙壁会反射信号形成多径效应,甚至空气湿度都能影响一点点。

所以我们从来不说“定位精度1米”这种大话。实测下来,开阔大厅平均误差1.8米,书架之间能干到3.5米,最差一次6米。结论是:找楼层没问题,找座位别指望

为了对抗RSSI的“情绪波动”,我们还加了个滑动窗口平滑——把最近5次定位结果取平均。稳定性提升了40%,代价是延迟多了3秒。这买卖划算。

五、去重篇:MAC地址的“5秒记忆”

同一个设备可能每秒发好几个Probe Request,要是不去重,数据就爆炸了。

我们的去重策略很朴素:维护一个MAC地址缓存,5秒内重复出现的MAC直接忽略

bool is_duplicate(uint8_t *mac) { for (int i = 0; i < CACHE_SIZE; i++) { if (memcmp(mac_cache[i].mac, mac, 6) == 0) { if (now - mac_cache[i].timestamp < 5000) { return true; // 5秒内重复,扔掉 } } } // 新MAC,记下来 }

就这么几行代码,能把数据量砍掉70%以上。有时候解决问题的办法就是这么朴实无华。

六、随机化篇:当“身份证”变成了“马甲”

前面说过,MAC地址是设备的“身份证”。但自从Android 10和iOS 14开始,手机们在扫描WiFi时会随机生成MAC地址。也就是说,同一部手机,每隔5-10分钟就换一件“马甲”。

这对我们来说是降维打击

本来想追踪“张三”在图书馆待了多久,结果“张三”待了6分钟变成了“李四”,“李四”又待了8分钟变成了“王五”。你还追个啥?

我们一开始很沮丧。后来想通了——我们到底要追“人”还是追“数”?

如果是追“数”——这层楼有多少设备——那随机化根本不是问题。不管马甲怎么换,总数就在那里。我们把每个随机MAC都当做一个独立的“观测样本”,统计总数和变化趋势。

放弃个体追踪,拥抱群体统计。这叫“因祸得福”——既规避了隐私风险,又简化了问题。

七、行为篇:占座与滞留的“硬规则”

有了位置数据,就能做点“聪明”的事情了。

占座检测的逻辑特别简单:如果某个设备在某片区域连续出现超过30分钟,而且RSSI几乎没怎么变(说明设备没怎么移动),就触发“占座疑似”告警。

闭馆滞留检测更简单:系统时间过了22:30,定位结果还在馆内的设备,统统告警。

这两个逻辑硬邦邦的,没有任何机器学习,没有任何深度学习,就是if-else

你可能会说:这也太糙了吧?

确实糙。有一次系统在23:00告警“有人滞留”,管理员跑过去一看——保洁阿姨的手机搁窗台上充电呢。手机不认识“阿姨”,只认识“信号”,它就老老实实报告“有设备”。这事儿告诉我们:任何自动化系统都需要人工复核,别指望机器替你搞定一切。

八、总结:不完美的实用主义

回过头来看这套系统,毛病一大堆:

  • 分时复用导致35秒延迟

  • RSSI抖动让定位精度飘忽不定

  • MAC随机化让个体追踪成了笑话

  • 占座检测会把充电的手机当成“占座党”

但你猜怎么着?图书馆管理员老李用得很开心

因为他不需要知道“张三在哪个座位”,他只需要知道“二楼现在人多不多,要不要加椅子”;他不需要精准到厘米,他只需要知道“闭馆了还有没有人没走”。

这就是我想说的:技术不是为了完美,是为了解决问题。用15块钱的东西、33字节的协议、加权平均的算法,去回答一个管理学的核心问题——“这层楼到底有多少人?”——这事儿,我觉得挺值的。

至于那些不完美的地方?留给下一版吧。毕竟,工程的真谛不是消灭所有bug,而是让bug都变得可控


(本文技术内容基于XX大学图书馆4节点WiFi探针系统的实际部署经验,数据真实可溯。欢迎复现,更欢迎吐槽。)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 14:24:08

Windows平台Android应用部署架构深度解析:APK Installer技术实现

Windows平台Android应用部署架构深度解析&#xff1a;APK Installer技术实现 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 在跨平台应用开发日益普及的今天&#xff…

作者头像 李华
网站建设 2026/7/14 14:22:53

MonoGame:跨平台游戏开发的.NET解决方案架构深度解析

MonoGame&#xff1a;跨平台游戏开发的.NET解决方案架构深度解析 【免费下载链接】MonoGame One framework for creating powerful cross-platform games. 项目地址: https://gitcode.com/gh_mirrors/mo/MonoGame 在当今游戏开发领域&#xff0c;跨平台兼容性已成为决定…

作者头像 李华
网站建设 2026/7/14 14:22:48

暗黑破坏神2存档编辑器终极指南:5分钟学会角色定制与装备修改

暗黑破坏神2存档编辑器终极指南&#xff1a;5分钟学会角色定制与装备修改 【免费下载链接】d2s-editor 项目地址: https://gitcode.com/gh_mirrors/d2/d2s-editor 还在为暗黑破坏神2中反复刷装备而烦恼吗&#xff1f;想快速体验不同职业Build却不想从头练级&#xff1f…

作者头像 李华
网站建设 2026/7/14 14:22:09

如何快速上手osmtogeojson?3分钟掌握OSM数据转换核心技能

如何快速上手osmtogeojson&#xff1f;3分钟掌握OSM数据转换核心技能 【免费下载链接】osmtogeojson convert osm to geojson 项目地址: https://gitcode.com/gh_mirrors/os/osmtogeojson 想要将OpenStreetMap&#xff08;OSM&#xff09;数据快速转换为GeoJSON格式吗&a…

作者头像 李华