doubleailes/tpms-sniffer
GitHub: doubleailes/tpms-sniffer
一个使用 Rust 编写的被动 TPMS 嗅探与车辆追踪解决方案,通过 RTL-SDR 解码并关联多协议信号以构建稳定轨迹。
Stars: 0 | Forks: 0
# tpms-sniffer
一个使用 Rust 编写的被动 TPMS(胎压监测系统)嗅探器和车辆追踪器。它使用低成本的 RTL-SDR 棒在 315/433 MHz 频段解码 25 种传感器协议的空中传输,并通过压力指纹识别和传输间隔分析将数据包关联为稳定的车辆轨迹。
## 概述
每辆配备直接 TPMS(dTPMS)的汽车都会以明文形式在 315 或 433 MHz 的 ISM 频段广播胎压和温度。这些信号在 40–50 米范围内可被接收,所需设备仅为约 30 美元的 RTL-SDR 棒。`tpms-sniffer` 可实时解码这些信号,并通过数据流构建持久的车辆身份标识——即使现代传感器会轮换标识符以规避追踪。
追踪器的处理流程如下:
```
RTL-SDR (IQ stream)
└─ Demodulator (OOK / FSK)
└─ Framer (preamble detection)
└─ Protocol decoders (25 protocols)
└─ Tracker (fingerprint correlator → vehicle UUIDs)
└─ SQLite store + JSON-L output
```
## 支持的协议
25 种协议源自 [rtl_433](https://github.com/merbanan/rtl_433) 参考实现。
| 标志 | 协议 | rtl_433 # | 车辆类型 | 频率 | 调制方式 |
|---|---|---|---|---|---|
| `steelmate` | Steelmate TPMS | 59 | 通用 | 315/433 | OOK-PWM |
| `schrader` | Schrader 通用 | 60 | 多种 | 315/433 | FSK-Manch |
| `citroen` | Citroën / Peugeot / Fiat VDO | 82 | Citroën、Peugeot、Fiat、Mitsubishi | 433 | FSK-Manch |
| `toyota` | Toyota PMV-C210 | 88 | Toyota Auris / Corolla / Lexus | 433 | FSK-DMC |
| `ford` | Ford / Continental VDO | 89 | Ford Fiesta / Focus / Kuga / Transit | 315/433 | FSK-Manch |
| `renault` | Renault / Dacia | 90 | Renault Clio / Captur / Zoe、Dacia | 433 | FSK-Manch |
| `schrader_eg53` | Schrader EG53MA4 | 95 | Saab、Opel、Vauxhall、Chevrolet | 315/433 | FSK-Manch |
| `toyota107j` | Toyota PMV-107J | 110 | 美国市场 Toyota | 315 | FSK-DMC |
| `jansite` | Jansite TY02S | 123 | 后市场 | 433 | OOK |
| `elantra` | Hyundai Elantra 2012 | 140 | Hyundai Elantra | 433 | OOK |
| `abarth` | Abarth 124 Spider | 156 | Abarth 124 | 433 | FSK-Manch |
| `schrader_smd` | Schrader SMD3MA4 / 3039 | 168 | Subaru、Infiniti、Nissan、Renault | 433 | FSK-Manch |
| `jansite_solar` | Jansite Solar | 180 | 后市场太阳能 | 433 | OOK |
| `hyundai_vdo` | Hyundai VDO | 186 | Hyundai、Kia、Genesis | 433 | FSK-Manch |
| `truck` | Solar / Truck TPMS | 201 | 卡车/重型后市场 | 433 | FSK-Manch |
| `porsche` | Porsche Boxster / Cayman | 203 | Porsche Boxster、Cayman | 433 | FSK-Manch |
| `ave` | AVE TPMS | 208 | 后市场粘贴式 | 433 | OOK |
| `tyreguard` | TyreGuard 400 | 225 | 通用后市场 | 433 | FSK-Manch |
| `eeztire` | EezTire E618 / Carchet / TST-507 | 241 | 外置粘贴式 | 433 | OOK |
| `bmw_gen45` | BMW Gen4/5 + Audi / HUF / Continental | 252 | BMW、Audi、VW | 433 | FSK-Manch |
| `bmw_gen23` | BMW Gen2/3 | 257 | BMW | 433 | FSK-Manch |
| `gm` | GM Aftermarket | 275 | 美国 GM 车型 | 315 | OOK |
| `airpuxem` | Airpuxem TYH11_EU6_ZQ | 295 | 后市场 | 433 | FSK-Manch |
| `trw_ook` | TRW OOK OEM + 克隆 | 298 | VW、Audi、Renault(OEM) | 433 | OOK |
| `trw_fsk` | TRW FSK OEM + 克隆 | 299 | VW、Audi、Renault(OEM) | 433 | FSK-Manch |
调制方式说明:
**OOK** = On-Off Keying,**FSK-Manch** = FSK + 曼彻斯特编码,**FSK-DMC** = FSK + 差分曼彻斯特编码。
## 硬件要求
- 任意兼容 RTL-SDR 的接收棒(RTL2832U 芯片组,约 25–35 美元)
- 针对 315 或 433 MHz ISM 频段调谐的天线
- Linux 或 macOS 主机
在开阔环境下的接收距离通常为 20–50 米。非视距(NLOS,通过墙体)接收可缩短距离。速度为 50 km/h 且在接收机 20 米范围内的车辆通常可产生 3–5 个数据包。
## 构建
```
# Linux
sudo apt install libusb-1.0-0-dev
# macOS
brew install libusb
cargo build --release
```
## 使用方法
```
# EU band (433.92 MHz, default)
./target/release/tpms-sniffer
# US band (315 MHz)
./target/release/tpms-sniffer --freq 315000000
# Decode only Ford sensors
./target/release/tpms-sniffer --protocol ford
# JSON output — pipe to jq, InfluxDB, the tracker, etc.
./target/release/tpms-sniffer --json | jq .
# High gain, lower confidence threshold
./target/release/tpms-sniffer --gain 400 --confidence 50
```
## 输出格式
### 人类可读(默认)
```
[2026-04-13 15:00:26] [241] EezTire/Carchet/TST-507 0xFFFFFFFF 51.1 kPa ( 7.4 psi) 205.0 °C conf=65% ⚠ALARM 🔋LOW raw=[FF FF FF FF FB FF FF EF FF]
[2026-04-13 15:00:26] [208] AVE-TPMS 0xFFFFBFFF 382.5 kPa ( 55.5 psi) 151.0 °C conf=65% raw=[FF FF BF FF FF BF]
[2026-04-13 15:02:22] [140] Hyundai-Elantra-2012 0xFFFFFFFF 253.0 kPa ( 36.7 psi) 215.0 °C conf=75% raw=[FF FF FF FF FD FF FF F7]
```
每一行包含:时间戳、协议 ID、协议名称、传感器 ID、压力(kPa 和 psi)、温度(°C)、置信度分数、报警/电池标志位以及原始字节。
### JSON(`--json`)
```
{
"timestamp": "2026-04-13 15:00:26.692",
"protocol": "EezTire/Carchet/TST-507",
"rtl433_id": 241,
"sensor_id": "0xFFFFFFFF",
"pressure_kpa": 51.1,
"pressure_psi": 7.4,
"temp_c": null,
"battery_ok": false,
"alarm": true,
"raw_hex": "FF FF FF FF FB FF FF EF FF",
"confidence": 65
}
```
当传感器报告保留值(≥ 200 °C)表示该字段不可用时,温度以 `null` 形式输出。
## 置信度评分
数据包在输出前会进行评分。默认阈值为 **65%**,可通过 `--confidence` 调整。
| 条件 | 得分 |
|---|---|
| CRC / 校验和通过 | +60 |
| 压力在合理范围内 | +20 |
| 压力在典型胎压范围(150–350 kPa)内 | +10 |
| 温度在典型范围(−20–80 °C)内 | +5 |
| 基础奖励 | +5 |
## 追踪器
追踪器消费来自嗅探器的 JSON-L 输出并构建稳定的车辆身份。运行方式如下:
```
./target/release/tpms-sniffer --json | ./target/release/tpms-tracker
```
### 车辆追踪原理
现代 TPMS 传感器(2018 年后、符合欧盟法规)会按数据包轮换传感器 ID 以防止被动追踪。追踪器同时处理固定 ID 和轮换 ID 的传感器:
- **固定 ID 传感器**(Hyundai、TRW-OOK、EezTire、大多数 OEM 协议):传感器 ID 在传感器生命周期内保持稳定。追踪器维护 `(sensor_id, protocol)` → `vehicle_uuid` 的映射。ID 中 `0xFFFFFFFF` 未被置位的位数少于 3 的视为解码伪像,并通过指纹相关器路由。
- **轮换 ID 传感器**(AVE-TPMS、2018 年后后市场产品):传感器 ID 每个数据包都会变化。追踪器通过 **压力指纹**(每个活跃车辆的中位压力值)和 **传输间隔**(连续数据包的时间中位值)进行关联。若两传感器压力均为 382.5 kPa 仍可能混淆;但若其传输间隔分别为 45 秒 71 秒,则可区分。
### 追踪器输出
```
2026-04-13 17:05:34 | vehicle=7178d3ed-f88f-4f00-8ad0-6ca8dace30e5 | sensor=0xFEFFFFFD | 63.8 kPa | TRW-OOK
2026-04-13 17:06:47 | vehicle=7178d3ed-f88f-4f00-8ad0-6ca8dace30e5 | sensor=0xFEFFFFFD | 63.8 kPa | TRW-OOK
2026-04-13 17:11:16 | vehicle=9d4c2a96-6392-4087-ba33-30d7ebae8f90 | sensor=0xFFFF7FFF | 334.5 kPa | AVE-TPMS
```
每条踪迹行携带一个稳定的 `vehicle` UUID,在会话期间即使传感器 ID 轮换也会持续存在。
### 调节参数
| 参数 | 默认值 | 描述 |
|---|---|---|
| `PRESSURE_TOLERANCE_KPA` | 5.0 | 指纹匹配的最大压力差值 |
| `VEHICLE_EXPIRY` | 300 秒(EezTire/TRW:480 秒,AVE:600 秒) | 轨迹静音过期时间 |
| `TX_INTERVAL_TOLERANCE_MS` | 8 000 | 传输间隔匹配容差 |
| `TX_INTERVAL_MIN_SAMPLES` | 3 | 使用 TX 匹配前的最小间隔样本数 |
## 架构
```
src/
├── demod.rs OOK envelope + FSK FM-discriminator, clock recovery
├── framer.rs Alternating (0xAA…) and Huf (0x00FF) preamble detection
├── manchester.rs Manchester and Differential Manchester decoders
├── decoder.rs 25 protocol decoders ported from rtl_433
└── reporter.rs Pretty-print and JSON-L output
tracker/
├── lib.rs Vehicle resolver (fixed-ID map + fingerprint correlator)
├── store.rs SQLite persistence layer
└── main.rs JSON-L ingestion loop
```
## 数据库架构
追踪器将踪迹持久化到本地 SQLite 数据库(默认为 `tpms.db`)。
```
CREATE TABLE vehicles (
vehicle_id TEXT PRIMARY KEY,
first_seen TEXT,
protocol TEXT,
rtl433_id INTEGER,
sensor_id TEXT,
make_model TEXT,
pressure_kpa REAL,
tx_interval_median_ms INTEGER
);
CREATE TABLE sightings (
id INTEGER PRIMARY KEY,
vehicle_id TEXT REFERENCES vehicles(vehicle_id),
ts TEXT,
pressure_kpa REAL,
temp_c REAL,
alarm INTEGER,
battery_ok INTEGER,
confidence INTEGER,
receiver_id TEXT NOT NULL DEFAULT 'default',
lat REAL,
lon REAL
);
```
## 研究背景
本工具实现了以下研究的成果:
追踪器的 Jaccard 共现分组(即将在后续版本中推出)直接基于该论文的第六章,展示了使用 1 分钟共现窗口可正确识别 12/12 辆车。
前人工作:Rouf 等,**《In-Car Wireless Networks 安全与隐私漏洞:TPMS 案例研究》**,USENIX Security 2010 —— 首次演示了 TPMS 可用于被动车辆追踪。
## 许可证
MIT
标签:315MHz, 433MHz, C2日志可视化, DMC, FSK, ISM频段, JSON-L, Manch, OOK, PWM, RTL-SDR, Rust, SQLite, TPMS, 二进制发布, 云资产清单, 传感器协议, 可视化界面, 实时解码, 射频信号, 开源工具, 持久身份, 指纹识别, 数据包解码, 无线嗅探, 标识符轮转, 汽车安全, 物联网, 网络流量审计, 胎压监测, 被动监听, 车辆跟踪, 车队追踪, 软件无线电, 逆向工程, 通知系统, 频谱分析