ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Fieldwatch 架构深度剖析:从空口一个广播包到列表一行,RF 监听全链路完整源码解析

Fieldwatch 架构深度剖析:从空口一个广播包到列表一行,RF 监听全链路完整源码解析 Fieldwatch 架构深度剖析从空口一个广播包到列表一行RF 监听全链路完整源码解析【免费下载链接】FieldwatchReceive-only Wi-Fi and Bluetooth LE observer for Android. MIT.项目地址: https://gitcode.com/gh_mirrors/fi/FieldwatchFieldwatch是一款只收发的 Android 无线监听工具Wi-Fi 接入点信标 蓝牙 LE 广播观测器被动监听、无后端服务器、无账号全部数据留在手机上。本文带你走完从空口一个广播包到列表一行的完整 RF 监听链路射频捕获 → 统一数据模型 → 服务编排 → 签名识别 → 列表生成并附上关键源码路径帮你一次读懂这套离线监听架构。一、先搞清楚Fieldwatch 在听什么一句话定义它的能力边界避免误解监听 Wi-Fi 接入点信标AP 广播能拿到 SSID、BSSID、信道、频率、厂商 IE、Wi-Fi 标准等监听蓝牙 LE 广播Advertisement能拿到广播名、厂商 ID、服务 UUID、厂商数据纯被动passive只收不发、不配对、不连接、无 dongle、无云端。它不是Wi-Fi 客户端/探针站、不是蓝牙经典设备、不是蜂窝、不做测向。理解这一点就理解了整套架构的设计前提——所有能力都围绕把空口被动收到的东西低延迟、可离线地变成屏幕上一行可读信息。 完整能力说明见官方手册 docs/Fieldwatch_User_Manual.pdf 与 docs/instruction.txt。二、全链路总览一个广播包的六步旅程把整个系统抽象成一条单向数据流每一站职责单一、可独立阅读站职责核心模块路径① 捕获从空口收广播/信标BleRadio / WifiRadioradio/BleRadio.kt、radio/WifiRadio.kt② 建模归一为统一观测对象Observation / Sightingdomain/Models.kt③ 编排通道批处理节流发布ScanServiceradio/ScanService.kt④ 识别签名匹配 / 厂商 OUISignatureEngine / DefaultCatalogdomain/SignatureEngine.kt、domain/DefaultCatalog.kt⑤ 生成刷新列表并驱动视图DeviceStore / Livedata/DeviceStore.kt、ui/screen/LiveScreens.kt⑥ 周边告警 / 记录 / TAK 发布Alerter / LogStore / TakPublishalert/Alerter.kt、data/LogStore.kt下面逐站拆解重点讲数据如何流动和为什么这样设计。三、第一站·射频捕获两个收音机如何听空口系统里只有两个真正的射频入口都通过回调把结果交回上层彼此完全解耦——这是全链路第一个解耦点。3.1 蓝牙 LE 广播BleRadioBleRadio基于 Android 的BluetoothLeScanner核心动作是全匹配扫描 逐包回调用空过滤器而非 unfiltered 列表匹配所有广播规避部分厂商在锁屏下的限制回调里对每个ScanResult调toObservation()解析出广播名、服务 UUID、厂商 ID、厂商数据、原始十六进制通过setCallbackType(CALLBACK_TYPE_ALL_MATCHES)MATCH_MODE_AGGRESSIVE拿到每一帧都上报保证不漏内置失败退避与周期回收needsRestart()应对三星等系统对长时 LOW_LATENCY 会话的挂起。关键转换发生在 BleRadio.kt#L216-L248一个空口ScanResult在这里变成一个结构化的Observation。注意注释里的一点——它只取空口广播名而不是本机的配对缓存名保证听到的是天上飞的不是本机存的。3.2 Wi-Fi 接入点信标WifiRadio 与系统配额Wi-Fi 侧的难点是Android 对startScan()的严格限流约每 30 秒一次Android 11 可查询是否被节流。WifiRadio为此做了一套完整的节流与配额管理双通道接收BroadcastReceiverSCAN_RESULTS_AVAILABLE_ACTION Android 11 的ScanResultsCallback兼顾新旧系统配额窗口QUOTA_SCANS4/QUOTA_WINDOW_MS120s自己再叠一层每 120 秒最多 4 次的软限流WifiRadio.kt#L205-L207快扫开关若开发者选项里关闭了系统节流可切到FAST_INTERVAL_MS8s的高频扫描fresh 语义只有自己发起的扫描才算新鲜结果避免把 OS 的缓存/部分集合误判为最新从而把别的 AP 老化掉。Wi-Fi 信标的归一在 WifiRadio.kt#L169-L203WifiIeParser解析信道、带宽、安全、厂商 IE再打包成同一个Observation。到这里两种射频已经收敛成同一种数据形状——这正是后两站能无差别处理的前提。四、第二站·统一数据模型Observation 与 Sighting全链路最关键的抽象在 domain/Models.kt只有两个数据对象却撑起了整条流Observation瞬态—— 空口收到的一帧字段包括kind、mac、name、rssi、channel、frequencyMhz、serviceUuids、manufacturerDataHex、rawHex等Models.kt#L851-L870。它是不可变的快照生命周期极短只用于在链路里流转。Sighting持久态—— 某台电台在本会话里被持续观测的样子在Observation之上叠加了firstSeen/lastSeen/hitCount、rssiHistory、presence在线区间、fleetIds命中的签名、rssiTrend等Models.kt#L702-L756。屏幕上列表的一行本质上就是一个Sighting。 设计要点Observation负责听得见Sighting负责认得出、看得见。二者之间由DeviceStore的 upsert 完成转换一次空口帧不会直接落到列表。五、第三站·编排中枢ScanService 的通道、批处理与发布节流radio/ScanService.kt 是整个链路的心脏也是全链路之所以能低延迟、低抖动的关键。它做三件事收、攒批、控频发布。5.1 一个 512 容量的背压通道两个射频的回调都汇入同一个协程通道ScanService.kt#L40inbound ChannelObservation(512, BufferOverflow.DROP_OLDEST)DROP_OLDEST是精髓当消费跟不上时丢最老的而不是阻塞射频回调线程。对被动观测场景丢一帧远比重启射频要好——永远不阻塞空口。5.2 攒批 位置打标 入库drainInbound()ScanService.kt#L141-L191每次最多攒 80 帧若开启位置打标给整批盖上当前 GPS 坐标调DeviceStore.ingestBatch()完成 upsert 签名打标对 BLE 命中调用pairingFlood.consider()识别配对洪泛写入坐席SitStore与日志LogStore并触发发布。5.3 200ms 发布节流把高频帧压成稳定刷新空口帧是高频的但 UI 不需要 60fps。schedulePublish()PUBLISH_MS 200LScanService.kt#L193-L209、ScanService.kt#L376把刷新去抖到 200ms 一次随后publishNow()ScanService.kt#L211-L257一次性完成刷新列表 → 跑告警 → 发 TAK。这就是广播包再多列表也稳如泰山的底层原因。六、第四站·身份识别签名匹配 厂商 OUI裸 MAC/广播包对人没意义识别层把它变成人话。签名匹配SignatureEngine对每个Sighting跑一批MatchRuleOUI、MAC 前缀、名称通配、服务 UUID、厂商 ID、厂商数据前缀等见 Models.kt#L219-L241。命中即把fleetIds挂上去Fleet.relabel()在入库时统一打标。内置目录DefaultCatalog出厂就带一批识别签名追踪器、信标、无人机、体戴、公网 AP 等配合radiodb厂商/OUI 表assets/lookups/radiodb.bin做厂商反查。BLE 清文字段解码签名可附带FleetDecode字段映射把厂商数据里的电池、状态、甚至经纬度解析出来直接显示在列表行上。 识别的产物决定了第六站的告警该响不响、该念什么——它是整条链路从包到意义的分水岭。七、第五站·列表生成StateFlow 刷新驱动 Live 视图设备状态用一个响应式流对外发布DeviceStore.kt#L28val devices: StateFlowListSighting _devices.asStateFlow()ingestBatch()DeviceStore.kt#L54-L69逐帧upsert再由refresh()DeviceStore.kt#L270按新鲜度/衰减清理最终把ListSighting推给StateFlow。UI 侧 ui/screen/LiveScreens.kt 只是这个流的纯投影——雷达、强度列表、时间线、按类分组都是同一份Sighting集合的不同视图。一句话列表的一行 一个Sighting 一帧空口广播在DeviceStore里不断 upsert 的累积结果。至此从空口一个广播包到列表一行的闭环完成。八、第六站·周边能力告警、记录、坐席与 TAK 发布同一份Sighting集合还被复用给四个旁路能力全部由publishNow()统一驱动告警Alerter命中观察列表的电台触发蜂鸣 / 语音 / 屏幕提示alert/Alerter.kt记录LogStore滚动 CSV/JSON 日志保留完整 MAC 与坐标data/LogStore.kt坐席SitStore把监听会话固化为可复盘的坐席报告data/SitStore.ktTAK 发布TakPublish向 ATAK/WinTAK 推送 UDP 光标目标domain/TakPublish.kt。这套一份数据、多路复用的结构让 Fieldwatch 在不增加空口负载的前提下扩展了告警、取证、协同三类场景。九、全链路关键点速查表环节关键设计源码锚点射频捕获空口逐帧回调两射频解耦BleRadio.kt#L208-L248数据归一Observation / Sighting 双模型Models.kt#L851-L870背压512 通道 DROP_OLDEST永不阻塞空口ScanService.kt#L40批处理攒批 80 帧 位置打标ScanService.kt#L141-L191刷新控频200ms 发布去抖ScanService.kt#L193-L209列表驱动StateFlow 投影多视图DeviceStore.kt#L28十、总结一条被动的完整管线回顾这条链路Fieldwatch 的架构精髓可以用一条主线串起来空口帧BleRadio/WifiRadio→ 归一快照Observation→ 背压通道512/DROP_OLDEST→ 攒批入库并签名识别DeviceStore SignatureEngine→ 200ms 节流发布 → StateFlow 驱动列表一行Sighting。它没有复杂框架靠的是单向数据流 单一职责 处处解耦射频不关心 UIUI 不关心射频中间用统一的Sighting模型和一条 200ms 节流的发布管线把所有高频空口噪声稳稳地压成屏幕上可读、可筛选、可告警、可取证的一行行电台。这正是被动、离线、低延迟三者能同时成立的根本原因也是这套 RF 监听架构最值得借鉴的设计。【免费下载链接】FieldwatchReceive-only Wi-Fi and Bluetooth LE observer for Android. MIT.项目地址: https://gitcode.com/gh_mirrors/fi/Fieldwatch创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表