2. J1939 PGN数据库查询工具
任务说明
实现一个命令行 PGN 查询工具:输入 PGN 号(十进制或 0x 十六进制),输出该 PGN 的名称、数据长度(字节)、发送频率和所属子系统。数据以本地字典形式内置,覆盖 J1939 常用 PGN。
环境与依赖
- Python 3.8+,仅用标准库,无需安装第三方包。
- 文件:
pgn_db.py(数据库与查询函数)、query.py(命令行入口)。
查询流程
核心代码
pgn_db.py:内置 PGN 元数据字典与查询函数。
PGN_DB = {
0xE800: {"name": "ECU1", "length": 8, "rate_ms": 100, "system": "Engine"},
0xE801: {"name": "ECU2", "length": 8, "rate_ms": 100, "system": "Engine"},
0xF004: {"name": "EngineSpeed", "length": 8, "rate_ms": 20, "system": "Engine"},
0xFEF1: {"name": "VehicleSpeed", "length": 8, "rate_ms": 100, "system": "Powertrain"},
0xFEE5: {"name": "AmbientConditions", "length": 8, "rate_ms": 1000, "system": "Cab"},
0xFEF2: {"name": "FuelConsumption", "length": 8, "rate_ms": 100, "system": "Powertrain"},
0xFECA: {"name": "DM1_ActiveDTC", "length": 8, "rate_ms": 1000, "system": "Diagnostics"},
0xFEDF: {"name": "SoftwareIdentification", "length": 8, "rate_ms": 0, "system": "Diagnostics"},
0xEA00: {"name": "TransmissionOilTemp", "length": 8, "rate_ms": 1000, "system": "Transmission"},
0xFEE9: {"name": "DashDisplay", "length": 8, "rate_ms": 100, "system": "Cab"},
}
def parse_pgn(text):
"""把用户输入解析为整数 PGN。支持十进制与 0x 前缀十六进制。"""
text = text.strip()
if text.lower().startswith("0x"):
return int(text, 16)
return int(text, 10)
def lookup_pgn(pgn):
"""返回元数据字典;未收录返回 None。"""
return PGN_DB.get(pgn)
def format_result(pgn, meta):
if meta is None:
return f"PGN 0x{pgn:04X} ({pgn}) 未收录于本地数据库。"
rate = "事件触发" if meta["rate_ms"] == 0 else f"{meta['rate_ms']} ms"
return (
f"PGN : 0x{pgn:04X} ({pgn})\n"
f"名称 : {meta['name']}\n"
f"数据长度 : {meta['length']} 字节\n"
f"发送频率 : {rate}\n"
f"所属子系统 : {meta['system']}"
)
query.py:命令行入口,支持参数或交互式输入。
import sys
from pgn_db import parse_pgn, lookup_pgn, format_result
def run(text):
try:
pgn = parse_pgn(text)
except ValueError:
print(f"无法解析 PGN: {text!r},请输入十进制或 0x 十六进制。")
return 1
print(format_result(pgn, lookup_pgn(pgn)))
return 0
if __name__ == "__main__":
if len(sys.argv) > 1:
sys.exit(run(sys.argv[1]))
print("输入 PGN(十进制或 0x 十六进制),空行退出:")
for line in sys.stdin:
line = line.strip()
if not line:
break
run(line)
运行与验证
# 命令行方式
python query.py 0xF004
python query.py 65262
# 交互方式
python query.py
通过条件:
python query.py 0xF004输出名称EngineSpeed、长度 8 字节、频率 20 ms、子系统 Engine。python query.py 65262(即 0xFEEE)输出“未收录于本地数据库”。- 输入非法字符串(如
abc)时打印解析失败提示并返回退出码 1。
扩展方式:向 PGN_DB 追加键值即可新增 PGN,键为整数 PGN 号,值为含 name/length/rate_ms/system 的字典;rate_ms=0 表示事件触发型报文。